strlen(gap_name)); } static ssize_t read_appearance(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { uint16_t appearance = sys_cpu_to_le16(gap_appearance); return bt_gatt_attr_read(conn, attr, buf, len, offset, &appearance, sizeof(appearance)); } static struct bt_gatt_attr attrs[] = { BT_GATT_PRIMARY_SERVICE(BT_UUID_GAP), BT_GATT_CHARACTERISTIC(BT_UUID_GAP_DEVICE_NAME, BT_GATT_CHRC_READ), BT_GATT_DESCRIPTOR(BT_UUID_GAP_DEVICE_NAME, BT_GATT_PERM_READ, read_name, NULL, NULL), BT_GATT_CHARACTERISTIC(BT_UUID_GAP_APPEARANCE, BT_GATT_CHRC_READ), BT_GATT_DESCRIPTOR(BT_UUID_GAP_APPEARANCE, BT_GATT_PERM_READ, read_appearance, NULL, NULL), }; void gap_init(const char *name, uint16_t appearance) { gap_name = name; gap_appearance = appearance; bt_gatt_register(attrs, ARRAY_SIZE(attrs)); }
pr_debug(LOG_MODULE_BLE, "RSCS enabled"); on_ble_rscs_enabled(); } else { /* Stop running speed and cadence sensor */ pr_debug(LOG_MODULE_BLE, "RSCS disabled"); on_ble_rscs_disabled(); } } /* RSC Service Declaration */ static const struct bt_gatt_attr rscs_attrs[] = { /* Running Speed and Cadence Service */ BT_GATT_PRIMARY_SERVICE(BT_UUID_RSCS), /* RSC Measurement */ BT_GATT_CHARACTERISTIC(BT_UUID_RSC_MEASUREMENT, BT_GATT_CHRC_NOTIFY), BT_GATT_DESCRIPTOR(BT_UUID_RSC_MEASUREMENT, 0, NULL, NULL, NULL), BT_GATT_CCC(rsc_measurement_ccc_cfg, rsc_measurement_ccc_cfg_changed), /* RSC Feature */ BT_GATT_CHARACTERISTIC(BT_UUID_RSC_FEATURE, BT_GATT_CHRC_READ), BT_GATT_DESCRIPTOR(BT_UUID_RSC_FEATURE, BT_GATT_PERM_READ, read_stepcadence_feature, NULL, NULL), #ifdef CONFIG_BLE_RSCS_SENSOR_LOCATION_SUPPORT /* Sensor Location*/ BT_GATT_CHARACTERISTIC(BT_UUID_SENSOR_LOCATION, BT_GATT_CHRC_READ), BT_GATT_DESCRIPTOR(BT_UUID_SENSOR_LOCATION, BT_GATT_PERM_READ, read_sensor_location, NULL, NULL), #endif };
static void att_find_info_rsp(struct bt_conn *conn, uint8_t err, const void *pdu, uint16_t length, void *user_data) { const struct bt_att_find_info_rsp *rsp = pdu; struct bt_gatt_discover_params *params = user_data; uint16_t handle = 0; uint8_t len; union { const struct bt_att_info_16 *i16; const struct bt_att_info_128 *i128; } info; union { struct bt_uuid uuid; struct bt_uuid_16 u16; struct bt_uuid_128 u128; } u; BT_DBG("err 0x%02x", err); if (err) { goto done; } /* Data can be either in UUID16 or UUID128 */ switch (rsp->format) { case BT_ATT_INFO_16: u.uuid.type = BT_UUID_TYPE_16; len = sizeof(*info.i16); break; case BT_ATT_INFO_128: u.uuid.type = BT_UUID_TYPE_128; len = sizeof(*info.i128); break; default: BT_ERR("Invalid format %u", rsp->format); goto done; } /* Parse descriptors found */ for (length--, pdu = rsp->info; length >= len; length -= len, pdu += len) { struct bt_gatt_attr *attr; info.i16 = pdu; handle = sys_le16_to_cpu(info.i16->handle); switch (u.uuid.type) { case BT_UUID_TYPE_16: u.u16.val = sys_le16_to_cpu(info.i16->uuid); break; case BT_UUID_TYPE_128: memcpy(u.u128.val, info.i128->uuid, 16); break; } BT_DBG("handle 0x%04x uuid %s", handle, bt_uuid_str(&u.uuid)); /* Skip if UUID is set but doesn't match */ if (params->uuid && bt_uuid_cmp(&u.uuid, params->uuid)) { continue; } attr = (&(struct bt_gatt_attr) BT_GATT_DESCRIPTOR(&u.uuid, 0, NULL, NULL, NULL)); attr->handle = handle; if (params->func(conn, attr, params) == BT_GATT_ITER_STOP) { return; } } /* Stop if could not parse the whole PDU */ if (length > 0) { goto done; } /* Next characteristic shall be after current value handle */ params->start_handle = handle; if (params->start_handle < UINT16_MAX) { params->start_handle++; } /* Stop if over the requested range */ if (params->start_handle >= params->end_handle) { goto done; } /* Continue to the next range */ if (!bt_gatt_discover(conn, params)) { return; } done: params->func(conn, NULL, params); }
/* Characteristic UUID of consumption power 71C9E918-8302-47AA-89D3-7BF67152237A */ static struct bt_uuid_128 consumption_power_uuid = BT_UUID_INIT_128( 0x7A, 0x23, 0x52, 0x71, 0xF6, 0x7B, 0xD3, 0x89, 0xAA, 0x47, 0x02, 0x83, 0x18, 0xE9, 0xC9, 0x71); /* Characteristic UUID of solar power 0609E802-AFD2-4D56-B61C-12BA1F80CCB6 */ static struct bt_uuid_128 solar_power_uuid = BT_UUID_INIT_128( 0xB6, 0xCC, 0x80, 0x1F, 0xBA, 0x12, 0x1C, 0xB6, 0x56, 0x4D, 0xD2, 0xAF, 0x02, 0xE8, 0x09, 0x06); static struct bt_gatt_attr attrs[] = { BT_GATT_PRIMARY_SERVICE(&power_uuid), BT_GATT_CHARACTERISTIC(&consumption_power_uuid.uuid, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY), BT_GATT_DESCRIPTOR(&consumption_power_uuid.uuid, BT_GATT_PERM_READ, read_u32, NULL, &consumption_value), BT_GATT_CUD(CONSUMPTION_CUD, BT_GATT_PERM_READ), BT_GATT_CCC(consumption_ccc_cfg, sensor_ccc_cfg_changed), BT_GATT_CHARACTERISTIC(&solar_power_uuid.uuid, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY), BT_GATT_DESCRIPTOR(&solar_power_uuid.uuid, BT_GATT_PERM_READ, read_u32, NULL, &solar_value), BT_GATT_CUD(SOLAR_CUD, BT_GATT_PERM_READ), BT_GATT_CCC(solar_ccc_cfg, sensor_ccc_cfg_changed) }; static void bt_ready(int err) { if (err) { printk("Bluetooth init failed (err %d)\n", err);
const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { uint8_t value = ble_hrs_sensor_location; return bt_gatt_attr_read(conn, attr, buf, len, offset, &value, sizeof(value)); } /* HRS Service Declaration */ static const struct bt_gatt_attr hrs_attrs[] = { BT_GATT_PRIMARY_SERVICE(BT_UUID_HRS), /* Heart Rate Measurement */ BT_GATT_CHARACTERISTIC(BT_UUID_HRS_MEASUREMENT, BT_GATT_CHRC_NOTIFY), BT_GATT_DESCRIPTOR(BT_UUID_HRS_MEASUREMENT, 0, NULL, NULL, NULL), BT_GATT_CCC(hrs_measurement_ccc_cfg, hrs_measurement_ccc_cfg_changed), /* Body Sensor Location */ BT_GATT_CHARACTERISTIC(BT_UUID_HRS_BODY_SENSOR, BT_GATT_CHRC_READ), BT_GATT_DESCRIPTOR(BT_UUID_HRS_BODY_SENSOR, BT_GATT_PERM_READ, read_body_sensor_location, NULL, NULL), BT_GATT_CCC(hrs_measurement_ccc_cfg, hrs_measurement_ccc_cfg_changed), }; /* Pointer to the HRS value attribute in the above table */ static struct bt_gatt_attr const *const hrs_value = &hrs_attrs[2]; int ble_hrs_init(void) { /* cast to discard the const qualifier */
printk("write_rgb: %x %x %x\n", rgb[0], rgb[1], rgb[2]); pwm_write(); return sizeof(rgb); } /* WebBT Service Declaration */ static struct bt_gatt_attr attrs[] = { BT_GATT_PRIMARY_SERVICE(BT_UUID_WEBBT), /* Temperature */ BT_GATT_CHARACTERISTIC(BT_UUID_TEMP, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY), BT_GATT_DESCRIPTOR(BT_UUID_TEMP, BT_GATT_PERM_READ, read_temperature, NULL, &temperature), BT_GATT_CUD(SENSOR_1_NAME, BT_GATT_PERM_READ), BT_GATT_CCC(blvl_ccc_cfg, blvl_ccc_cfg_changed), /* RGB Led */ BT_GATT_CHARACTERISTIC(BT_UUID_RGB, BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE), BT_GATT_DESCRIPTOR(BT_UUID_RGB, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE, read_rgb, write_rgb, rgb), BT_GATT_CUD(SENSOR_2_NAME, BT_GATT_PERM_READ), }; void temperature_ipm_callback(void *context, uint32_t id, volatile void *data) { struct bt_conn *conn = (struct bt_conn *) context;
sizeof(supported_locations)); return len; default: status = SC_CP_RSP_OP_NOT_SUPP; } ctrl_point_ind(conn, req->op, status, NULL, 0); return len; } static struct bt_gatt_attr csc_attrs[] = { BT_GATT_PRIMARY_SERVICE(BT_UUID_CSC), BT_GATT_CHARACTERISTIC(BT_UUID_CSC_MEASUREMENT, BT_GATT_CHRC_NOTIFY), BT_GATT_DESCRIPTOR(BT_UUID_CSC_MEASUREMENT, 0x00, NULL, NULL, NULL), BT_GATT_CCC(csc_meas_ccc_cfg, csc_meas_ccc_cfg_changed), BT_GATT_CHARACTERISTIC(BT_UUID_SENSOR_LOCATION, BT_GATT_CHRC_READ), BT_GATT_DESCRIPTOR(BT_UUID_SENSOR_LOCATION, BT_GATT_PERM_READ, read_location, NULL, &sensor_location), BT_GATT_CHARACTERISTIC(BT_UUID_CSC_FEATURE, BT_GATT_CHRC_READ), BT_GATT_DESCRIPTOR(BT_UUID_CSC_FEATURE, BT_GATT_PERM_READ, read_csc_feature, NULL, NULL), BT_GATT_CHARACTERISTIC(BT_UUID_SC_CONTROL_POINT, BT_GATT_CHRC_WRITE | BT_GATT_CHRC_INDICATE), BT_GATT_DESCRIPTOR(BT_UUID_SC_CONTROL_POINT, BT_GATT_PERM_WRITE, NULL, write_ctrl_point, &sensor_location), BT_GATT_CCC(ctrl_point_ccc_cfg, ctrl_point_ccc_cfg_changed), }; struct sc_ctrl_point_ind {
return len; } static const struct bt_uuid_128 vnd_signed_uuid = BT_UUID_INIT_128( 0xf3, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x13, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x13); /* Vendor Primary Service Declaration */ static struct bt_gatt_attr vnd_attrs[] = { /* Vendor Primary Service Declaration */ BT_GATT_PRIMARY_SERVICE(&vnd_uuid), BT_GATT_CHARACTERISTIC(&vnd_enc_uuid.uuid, BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | BT_GATT_CHRC_INDICATE), BT_GATT_DESCRIPTOR(&vnd_enc_uuid.uuid, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, read_vnd, write_vnd, vnd_value), BT_GATT_CCC(vnd_ccc_cfg, vnd_ccc_cfg_changed), BT_GATT_CHARACTERISTIC(&vnd_auth_uuid.uuid, BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE), BT_GATT_DESCRIPTOR(&vnd_auth_uuid.uuid, BT_GATT_PERM_READ_AUTHEN | BT_GATT_PERM_WRITE_AUTHEN, read_vnd, write_vnd, vnd_value), BT_GATT_CHARACTERISTIC(&vnd_long_uuid.uuid, BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | BT_GATT_CHRC_EXT_PROP), BT_GATT_DESCRIPTOR(&vnd_long_uuid.uuid, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE, read_long_vnd, write_long_vnd, &vnd_long_value), BT_GATT_CEP(&vnd_long_cep), BT_GATT_CHARACTERISTIC(&vnd_signed_uuid.uuid, BT_GATT_CHRC_READ |
static ssize_t read_blvl(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { const char *value = attr->user_data; return bt_gatt_attr_read(conn, attr, buf, len, offset, value, sizeof(*value)); } /* Battery Service Declaration */ static struct bt_gatt_attr attrs[] = { BT_GATT_PRIMARY_SERVICE(BT_UUID_BAS), BT_GATT_CHARACTERISTIC(BT_UUID_BAS_BATTERY_LEVEL, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY), BT_GATT_DESCRIPTOR(BT_UUID_BAS_BATTERY_LEVEL, BT_GATT_PERM_READ, read_blvl, NULL, &battery), BT_GATT_CCC(blvl_ccc_cfg, blvl_ccc_cfg_changed), }; void bas_init(void) { bt_gatt_register(attrs, ARRAY_SIZE(attrs)); } void bas_notify(void) { if (!simulate_blvl) { return; } battery--;
static ssize_t read_u32(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { const uint32_t *u32 = attr->user_data; uint32_t value = sys_cpu_to_le32(*u32); return bt_gatt_attr_read(conn, attr, buf, len, offset, &value, sizeof(value)); } static struct bt_gatt_attr attrs[] = { BT_GATT_PRIMARY_SERVICE(BT_UUID_ESS), BT_GATT_CHARACTERISTIC(BT_UUID_TEMPERATURE, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY), BT_GATT_DESCRIPTOR(BT_UUID_TEMPERATURE, BT_GATT_PERM_READ, read_u16, NULL, &temp_value), BT_GATT_CUD(TEMPERATURE_CUD, BT_GATT_PERM_READ), BT_GATT_CCC(temp_ccc_cfg, sensor_ccc_cfg_changed), BT_GATT_CHARACTERISTIC(BT_UUID_HUMIDITY, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY), BT_GATT_DESCRIPTOR(BT_UUID_HUMIDITY, BT_GATT_PERM_READ, read_u16, NULL, &humidity_value), BT_GATT_CUD(HUMIDITY_CUD, BT_GATT_PERM_READ), BT_GATT_CCC(humidity_ccc_cfg, sensor_ccc_cfg_changed), BT_GATT_CHARACTERISTIC(BT_UUID_PRESSURE, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY), BT_GATT_DESCRIPTOR(BT_UUID_PRESSURE, BT_GATT_PERM_READ, read_u32, NULL, &pressure_value), BT_GATT_CUD(PRESSURE_CUD, BT_GATT_PERM_READ),
} static ssize_t read_appearance(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { uint16_t appearance = sys_cpu_to_le16(CSC_APPEARANCE); return bt_gatt_attr_read(conn, attr, buf, len, offset, &appearance, sizeof(appearance)); } static struct bt_gatt_attr gap_attrs[] = { BT_GATT_PRIMARY_SERVICE(BT_UUID_GAP), BT_GATT_CHARACTERISTIC(BT_UUID_GAP_DEVICE_NAME, BT_GATT_CHRC_READ), BT_GATT_DESCRIPTOR(BT_UUID_GAP_DEVICE_NAME, BT_GATT_PERM_READ, read_device_name, NULL, DEVICE_NAME), BT_GATT_CHARACTERISTIC(BT_UUID_GAP_APPEARANCE, BT_GATT_CHRC_READ), BT_GATT_DESCRIPTOR(BT_UUID_GAP_APPEARANCE, BT_GATT_PERM_READ, read_appearance, NULL, NULL), }; /* Device Information Service declaration */ static ssize_t read_model(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { const char *value = attr->user_data; return bt_gatt_attr_read(conn, attr, buf, len, offset, value, strlen(value)); }
strlen(value)); } static int read_manuf(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { const char *value = attr->user_data; return bt_gatt_attr_read(conn, attr, buf, len, offset, value, strlen(value)); } static struct bt_gatt_attr attrs[] = { BT_GATT_PRIMARY_SERVICE(BT_UUID_GAP), BT_GATT_CHARACTERISTIC(BT_UUID_GAP_DEVICE_NAME, BT_GATT_CHRC_READ), BT_GATT_DESCRIPTOR(BT_UUID_GAP_DEVICE_NAME, BT_GATT_PERM_READ, read_name, NULL, DEVICE_NAME), BT_GATT_CHARACTERISTIC(BT_UUID_GAP_APPEARANCE, BT_GATT_CHRC_READ), BT_GATT_DESCRIPTOR(BT_UUID_GAP_APPEARANCE, BT_GATT_PERM_READ, read_appearance, NULL, NULL), /* Device Information Service Declaration */ BT_GATT_PRIMARY_SERVICE(BT_UUID_DIS), BT_GATT_CHARACTERISTIC(BT_UUID_DIS_MODEL_NUMBER, BT_GATT_CHRC_READ), BT_GATT_DESCRIPTOR(BT_UUID_DIS_MODEL_NUMBER, BT_GATT_PERM_READ, read_model, NULL, CONFIG_SOC), BT_GATT_CHARACTERISTIC(BT_UUID_DIS_MANUFACTURER_NAME, BT_GATT_CHRC_READ), BT_GATT_DESCRIPTOR(BT_UUID_DIS_MANUFACTURER_NAME, BT_GATT_PERM_READ, read_manuf, NULL, "Manufacturer"), }; static const struct bt_data ad[] = {