bool gatt_db_attribute_get_service_uuid(const struct gatt_db_attribute *attrib, bt_uuid_t *uuid) { struct gatt_db_service *service; if (!attrib || !uuid) return false; service = attrib->service; if (service->attributes[0]->value_len == sizeof(uint16_t)) { uint16_t value; value = get_le16(service->attributes[0]->value); bt_uuid16_create(uuid, value); return true; } if (service->attributes[0]->value_len == sizeof(uint128_t)) { uint128_t value; bswap_128(service->attributes[0]->value, &value); bt_uuid128_create(uuid, value); return true; } return false; }
static int bt_string_to_uuid128(bt_uuid_t *uuid, const char *string) { uint32_t data0, data4; uint16_t data1, data2, data3, data5; uint128_t u128; uint8_t *val = (uint8_t *) &u128; if (sscanf(string, "%08x-%04hx-%04hx-%04hx-%08x%04hx", &data0, &data1, &data2, &data3, &data4, &data5) != 6) return -EINVAL; data0 = htonl(data0); data1 = htons(data1); data2 = htons(data2); data3 = htons(data3); data4 = htonl(data4); data5 = htons(data5); memcpy(&val[0], &data0, 4); memcpy(&val[4], &data1, 2); memcpy(&val[6], &data2, 2); memcpy(&val[8], &data3, 2); memcpy(&val[10], &data4, 4); memcpy(&val[14], &data5, 2); bt_uuid128_create(uuid, u128); return 0; }
static void get_uuid(uint8_t type, const void *val, bt_uuid_t *uuid) { if (type == BT_UUID16) bt_uuid16_create(uuid, get_le16(val)); else { uint128_t u128; /* Convert from 128-bit LE to BE */ bswap_128(val, &u128); bt_uuid128_create(uuid, u128); } }
static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct att_data_list *list; guint8 format; int i; if (status != 0) { g_printerr("Discover all characteristic descriptors failed: " "%s\n", att_ecode2str(status)); goto done; } list = dec_find_info_resp(pdu, plen, &format); if (list == NULL) goto done; for (i = 0; i < list->num; i++) { char uuidstr[MAX_LEN_UUID_STR]; uint16_t handle; uint8_t *value; bt_uuid_t uuid; value = list->data[i]; handle = get_le16(value); if (format == ATT_FIND_INFO_RESP_FMT_16BIT) bt_uuid16_create(&uuid, get_le16(&value[2])); else { uint128_t u128; /* Converts from LE to BE byte order */ bswap_128(&value[2], &u128); bt_uuid128_create(&uuid, u128); } bt_uuid_to_string(&uuid, uuidstr, MAX_LEN_UUID_STR); g_print("handle = 0x%04x, uuid = %s\n", handle, uuidstr); } att_data_list_free(list); done: if (!opt_listen) g_main_loop_quit(event_loop); }
static bool get_uuid_le(const uint8_t *uuid, size_t len, bt_uuid_t *out_uuid) { uint128_t u128; switch (len) { case 2: bt_uuid16_create(out_uuid, get_le16(uuid)); return true; case 16: bswap_128(uuid, &u128.data); bt_uuid128_create(out_uuid, u128); return true; default: return false; } return false; }
static bool le_to_uuid(const uint8_t *src, size_t len, bt_uuid_t *uuid) { uint128_t u128; if (len == 2) { bt_uuid16_create(uuid, get_le16(src)); return true; } if (len == 4) { bt_uuid32_create(uuid, get_le32(src)); return true; } if (len != 16) return false; bswap_128(src, &u128); bt_uuid128_create(uuid, u128); return true; }
static void register_weight_service(struct gatt_example_adapter *adapter, const uint16_t vendor[2]) { const char *desc_weight = "Rucksack Weight"; const uint128_t char_weight_uuid_btorder = { .data = { 0x80, 0x88, 0xF2, 0x18, 0x90, 0x2C, 0x45, 0x0B, 0xB6, 0xC4, 0x62, 0x89, 0x1E, 0x8C, 0x25, 0xE9 } }; const uint128_t prim_weight_uuid_btorder = { .data = { 0x4F, 0x0A, 0xC0, 0x96, 0x35, 0xD4, 0x49, 0x11, 0x96, 0x31, 0xDE, 0xA8, 0xDC, 0x74, 0xEE, 0xFE } }; uint128_t prim_weight_uuid, char_weight_uuid; uint16_t start_handle, h; const int svc_size = 6; uint32_t sdp_handle; uint8_t atval[256]; bt_uuid_t uuid; int len; btoh128(&char_weight_uuid_btorder, &char_weight_uuid); btoh128(&prim_weight_uuid_btorder, &prim_weight_uuid); bt_uuid128_create(&uuid, prim_weight_uuid); start_handle = attrib_db_find_avail(adapter->adapter, &uuid, svc_size); if (start_handle == 0) { error("Not enough free handles to register service"); return; } DBG("start_handle=0x%04x, vendor=0x%04x-0x%04x", start_handle, vendor[0], vendor[1]); h = start_handle; /* Weight service: primary service definition */ bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID); memcpy(atval, &prim_weight_uuid_btorder, 16); attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 16); if (vendor[0] && vendor[1]) { /* Weight: include */ bt_uuid16_create(&uuid, GATT_INCLUDE_UUID); att_put_u16(vendor[0], &atval[0]); att_put_u16(vendor[1], &atval[2]); att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]); attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6); } /* Weight: characteristic */ bt_uuid16_create(&uuid, GATT_CHARAC_UUID); atval[0] = ATT_CHAR_PROPER_READ; att_put_u16(h + 1, &atval[1]); memcpy(&atval[3], &char_weight_uuid_btorder, 16); attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 19); /* Weight: characteristic value */ bt_uuid128_create(&uuid, char_weight_uuid); atval[0] = 0x82; atval[1] = 0x55; atval[2] = 0x00; atval[3] = 0x00; attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 4); /* Weight: characteristic format */ bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID); atval[0] = 0x08; atval[1] = 0xFD; att_put_u16(FMT_KILOGRAM_UUID, &atval[2]); att_put_u16(BLUETOOTH_SIG_UUID, &atval[4]); att_put_u16(FMT_HANGING_UUID, &atval[6]); attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8); /* Weight: characteristic user description */ bt_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID); len = strlen(desc_weight); strncpy((char *) atval, desc_weight, len); attrib_db_add(adapter->adapter, h, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len); g_assert(h - start_handle + 1 == svc_size); /* Add an SDP record for the above service */ sdp_handle = attrib_create_sdp(adapter->adapter, start_handle, "Weight Service"); if (sdp_handle) adapter->sdp_handles = g_slist_prepend(adapter->sdp_handles, GUINT_TO_POINTER(sdp_handle)); }