* [PATCH 0/1] SDP registration of Primary GATT Services @ 2011-02-18 20:11 Brian Gix 2011-02-18 20:11 ` [PATCH 1/1] Add SDP registration of Primary GATT services Brian Gix 0 siblings, 1 reply; 3+ messages in thread From: Brian Gix @ 2011-02-18 20:11 UTC (permalink / raw) To: linux-bluetooth; +Cc: johan.hedberg, padovan, anderson.lizardo This addresses Anderson's issue with the SDP registration. It maintains the prior APIs and adds a couple which can be called any time after a complete Primary Service has been inserted into the attribute database. This allows the attrib-server user to pick and choose the services he wants to expose to BR/EDR devices, as opposed to LE only devices. It also gives a mechanism to remove the SDP record from the SDP db. It also has improved naming (attrib_*) to tie all the parts together. -- Brian Gix bgix@codeaurora.org Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum ^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/1] Add SDP registration of Primary GATT services 2011-02-18 20:11 [PATCH 0/1] SDP registration of Primary GATT Services Brian Gix @ 2011-02-18 20:11 ` Brian Gix 2011-02-18 20:20 ` Brian Gix 0 siblings, 1 reply; 3+ messages in thread From: Brian Gix @ 2011-02-18 20:11 UTC (permalink / raw) To: linux-bluetooth; +Cc: johan.hedberg, padovan, anderson.lizardo, Brian Gix Add capability to register SDP record for Primary Services. --- attrib/example.c | 29 +++++++++- src/attrib-server.c | 162 +++++++++++++++++++++++++++++++++++++++------------ src/attrib-server.h | 2 + 3 files changed, 155 insertions(+), 38 deletions(-) diff --git a/attrib/example.c b/attrib/example.c index 1911912..f0648e4 100644 --- a/attrib/example.c +++ b/attrib/example.c @@ -59,6 +59,9 @@ #define FMT_KILOGRAM_UUID 0xA010 #define FMT_HANGING_UUID 0xA011 +#define SDP_RECORD_COUNT 10 +uint32_t sdp_handles[SDP_RECORD_COUNT]; + static int register_attributes(void) { const char *desc_out_temp = "Outside Temperature"; @@ -77,6 +80,7 @@ static int register_attributes(void) uint8_t atval[256]; uuid_t uuid; int len; + int i = 0; /* Battery state service: primary service definition */ sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID); @@ -101,6 +105,11 @@ static int register_attributes(void) atval[1] = 0x00; attrib_db_add(0x0111, &uuid, ATT_NONE, ATT_AUTHENTICATION, atval, 2); + /* Add an SDP record for the above service */ + sdp_handles[i] = attrib_create_sdp(0x0100, "Battery State Service"); + if (sdp_handles[i]) + i++; + /* Thermometer: primary service definition */ sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID); att_put_u16(THERM_HUMIDITY_SVC_UUID, &atval[0]); @@ -116,7 +125,8 @@ static int register_attributes(void) /* Thermometer: Include */ att_put_u16(0x0550, &atval[0]); att_put_u16(0x0568, &atval[2]); - attrib_db_add(0x0202, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 4); + att_put_u16(VENDOR_SPECIFIC_SVC_UUID, &atval[4]); + attrib_db_add(0x0202, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6); /* Thermometer: temperature characteristic */ sdp_uuid16_create(&uuid, GATT_CHARAC_UUID); @@ -173,6 +183,11 @@ static int register_attributes(void) strncpy((char *) atval, desc_out_hum, len); attrib_db_add(0x0214, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len); + /* Add an SDP record for the above service */ + sdp_handles[i] = attrib_create_sdp(0x0200, "Thermometer"); + if (sdp_handles[i]) + i++; + /* Secondary Service: Manufacturer Service */ sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID); att_put_u16(MANUFACTURER_SVC_UUID, &atval[0]); @@ -299,6 +314,11 @@ static int register_attributes(void) strncpy((char *) atval, desc_weight, len); attrib_db_add(0x0685, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len); + /* Add an SDP record for the above service */ + sdp_handles[i] = attrib_create_sdp(0x0680, "Weight Service"); + if (sdp_handles[i]) + i++; + return 0; } @@ -309,4 +329,11 @@ int server_example_init(void) void server_example_exit(void) { + int i; + + for (i = 0; i < SDP_RECORD_COUNT; i++) + if (sdp_handles[i]) { + attrib_free_sdp(sdp_handles[i]); + sdp_handles[i] = 0; + } } diff --git a/src/attrib-server.c b/src/attrib-server.c index 85b39a8..c6438bd 100644 --- a/src/attrib-server.c +++ b/src/attrib-server.c @@ -70,7 +70,8 @@ struct group_elem { static GIOChannel *l2cap_io = NULL; static GIOChannel *le_io = NULL; static GSList *clients = NULL; -static uint32_t sdp_handle = 0; +static uint32_t gatt_sdp_handle = 0; +static uint32_t gap_sdp_handle = 0; static uuid_t prim_uuid = { .type = SDP_UUID16, @@ -81,14 +82,19 @@ static uuid_t snd_uuid = { .value.uuid16 = GATT_SND_SVC_UUID }; -static sdp_record_t *server_record_new(void) +static sdp_record_t *server_record_new(uuid_t *uuid, uint16_t start, uint16_t end) { - sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto; + sdp_list_t *svclass_id, *apseq, *proto[2], *root, *aproto; uuid_t root_uuid, proto_uuid, gatt_uuid, l2cap; - sdp_profile_desc_t profile; sdp_record_t *record; sdp_data_t *psm, *sh, *eh; - uint16_t lp = GATT_PSM, start = 0x0001, end = 0xffff; + uint16_t lp = GATT_PSM; + + if (uuid == NULL) + return NULL; + + if (start > end) + return NULL; record = sdp_record_alloc(); if (record == NULL) @@ -99,17 +105,10 @@ static sdp_record_t *server_record_new(void) sdp_set_browse_groups(record, root); sdp_list_free(root, NULL); - sdp_uuid16_create(&gatt_uuid, GENERIC_ATTRIB_SVCLASS_ID); - svclass_id = sdp_list_append(NULL, &gatt_uuid); + svclass_id = sdp_list_append(NULL, uuid); sdp_set_service_classes(record, svclass_id); sdp_list_free(svclass_id, NULL); - sdp_uuid16_create(&profile.uuid, GENERIC_ATTRIB_PROFILE_ID); - profile.version = 0x0100; - profiles = sdp_list_append(NULL, &profile); - sdp_set_profile_descs(record, profiles); - sdp_list_free(profiles, NULL); - sdp_uuid16_create(&l2cap, L2CAP_UUID); proto[0] = sdp_list_append(NULL, &l2cap); psm = sdp_data_alloc(SDP_UINT16, &lp); @@ -127,11 +126,6 @@ static sdp_record_t *server_record_new(void) aproto = sdp_list_append(NULL, apseq); sdp_set_access_protos(record, aproto); - sdp_set_info_attr(record, "Generic Attribute Profile", "BlueZ", NULL); - - sdp_set_url_attr(record, "http://www.bluez.org/", - "http://www.bluez.org/", "http://www.bluez.org/"); - sdp_set_service_id(record, gatt_uuid); sdp_data_free(psm); @@ -176,6 +170,40 @@ static uint8_t att_check_reqs(struct gatt_channel *channel, uint8_t opcode, return 0; } +static struct attribute *find_primary_range(uint16_t start, uint16_t *end) +{ + struct attribute *a, *attrib = NULL; + GSList *l; + gboolean found = FALSE; + + if (end == NULL) + return NULL; + + for (l = database; l; l = l->next) { + a = l->data; + + if (a->handle < start) + continue; + + if ((a->handle == start) && + sdp_uuid_cmp(&a->uuid, &prim_uuid) == 0) { + found = TRUE; + *end = start; + attrib = a; + continue; + } else if (!found) + break; + + if (sdp_uuid_cmp(&a->uuid, &prim_uuid) == 0 || + sdp_uuid_cmp(&a->uuid, &snd_uuid) == 0) + break; + else + *end = a->handle; + } + + return attrib; +} + static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start, uint16_t end, uuid_t *uuid, uint8_t *pdu, int len) @@ -607,7 +635,7 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle, static uint16_t mtu_exchange(struct gatt_channel *channel, uint16_t mtu, uint8_t *pdu, int len) { - channel->mtu = MIN(mtu, ATT_MAX_MTU); + channel->mtu = MIN(mtu, channel->mtu); return enc_mtu_resp(channel->mtu, pdu, len); } @@ -794,7 +822,7 @@ static void confirm_event(GIOChannel *io, void *user_data) return; } -static void register_core_services(void) +static gboolean register_core_services(void) { uint8_t atval[256]; uuid_t uuid; @@ -820,17 +848,37 @@ static void register_core_services(void) /* TODO: Implement Appearance characteristic. It is mandatory for * Peripheral/Central GAP roles. */ + gap_sdp_handle = attrib_create_sdp(0x0001, "Generic Access Profile"); + + if (gap_sdp_handle == 0) { + error("Failed to register GAP service record"); + goto failed; + } /* GATT service: primary service definition */ sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID); att_put_u16(GENERIC_ATTRIB_PROFILE_ID, &atval[0]); attrib_db_add(0x0010, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2); + + gatt_sdp_handle = attrib_create_sdp(0x0010, + "Generic Attribute Profile"); + if (gatt_sdp_handle == 0) { + error("Failed to register GATT service record"); + goto failed; + } + + return TRUE; + +failed: + if (gap_sdp_handle) + remove_record_from_server(gap_sdp_handle); + + return FALSE; } int attrib_server_init(void) { GError *gerr = NULL; - sdp_record_t *record; /* BR/EDR socket */ l2cap_io = bt_io_listen(BT_IO_L2CAP, NULL, confirm_event, @@ -846,21 +894,8 @@ int attrib_server_init(void) return -1; } - record = server_record_new(); - if (record == NULL) { - error("Unable to create GATT service record"); + if (!register_core_services()) goto failed; - } - - if (add_record_to_server(BDADDR_ANY, record) < 0) { - error("Failed to register GATT service record"); - sdp_record_free(record); - goto failed; - } - - sdp_handle = record->handle; - - register_core_services(); if (!main_opts.le) return 0; @@ -919,8 +954,61 @@ void attrib_server_exit(void) g_slist_free(clients); - if (sdp_handle) - remove_record_from_server(sdp_handle); + if (gatt_sdp_handle) + remove_record_from_server(gatt_sdp_handle); + + if (gap_sdp_handle) + remove_record_from_server(gap_sdp_handle); +} + +uint32_t attrib_create_sdp(uint16_t handle, const char *name) +{ + sdp_record_t *record; + struct attribute *a; + uint16_t end = 0; + uuid_t svc; + + a = find_primary_range(handle, &end); + + if (a == NULL) + goto failed; + + if (a->len == 2) { + svc.type = SDP_UUID16; + svc.value.uuid16 = att_get_u16(a->data); + } else if (a->len == 16) { + svc.type = SDP_UUID128; + memcpy(&svc.value.uuid128, a->data, sizeof(uint128_t)); + } else + goto failed; + + record = server_record_new(&svc, handle, end); + + if (record == NULL) + goto failed; + + if (name) + sdp_set_info_attr(record, name, "BlueZ", NULL); + + if (svc.type == SDP_UUID16 && + svc.value.uuid16 == GENERIC_ACCESS_PROFILE_ID) { + sdp_set_url_attr(record, "http://www.bluez.org/", + "http://www.bluez.org/", + "http://www.bluez.org/"); + } + + if (add_record_to_server(BDADDR_ANY, record) < 0) + sdp_record_free(record); + else + return record->handle; + +failed: + return 0; +} + +void attrib_free_sdp(uint32_t sdp_handle) +{ + remove_record_from_server(sdp_handle); } int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs, diff --git a/src/attrib-server.h b/src/attrib-server.h index ba90ff4..34236e4 100644 --- a/src/attrib-server.h +++ b/src/attrib-server.h @@ -30,3 +30,5 @@ int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs, int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value, int len); int attrib_db_del(uint16_t handle); +uint32_t attrib_create_sdp(uint16_t handle, const char *name); +void attrib_free_sdp(uint32_t sdp_handle); -- 1.7.1 -- Brian Gix bgix@codeaurora.org Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 1/1] Add SDP registration of Primary GATT services 2011-02-18 20:11 ` [PATCH 1/1] Add SDP registration of Primary GATT services Brian Gix @ 2011-02-18 20:20 ` Brian Gix 0 siblings, 0 replies; 3+ messages in thread From: Brian Gix @ 2011-02-18 20:20 UTC (permalink / raw) To: Brian Gix; +Cc: linux-bluetooth, johan.hedberg, padovan, anderson.lizardo Please ignore --> I have some merging to do. On 2/18/2011 12:11 PM, Brian Gix wrote: > Add capability to register SDP record for Primary Services. > --- > attrib/example.c | 29 +++++++++- > src/attrib-server.c | 162 +++++++++++++++++++++++++++++++++++++++------------ > src/attrib-server.h | 2 + > 3 files changed, 155 insertions(+), 38 deletions(-) > > diff --git a/attrib/example.c b/attrib/example.c > index 1911912..f0648e4 100644 > --- a/attrib/example.c > +++ b/attrib/example.c > @@ -59,6 +59,9 @@ > #define FMT_KILOGRAM_UUID 0xA010 > #define FMT_HANGING_UUID 0xA011 > > +#define SDP_RECORD_COUNT 10 > +uint32_t sdp_handles[SDP_RECORD_COUNT]; > + > static int register_attributes(void) > { > const char *desc_out_temp = "Outside Temperature"; > @@ -77,6 +80,7 @@ static int register_attributes(void) > uint8_t atval[256]; > uuid_t uuid; > int len; > + int i = 0; > > /* Battery state service: primary service definition */ > sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID); > @@ -101,6 +105,11 @@ static int register_attributes(void) > atval[1] = 0x00; > attrib_db_add(0x0111,&uuid, ATT_NONE, ATT_AUTHENTICATION, atval, 2); > > + /* Add an SDP record for the above service */ > + sdp_handles[i] = attrib_create_sdp(0x0100, "Battery State Service"); > + if (sdp_handles[i]) > + i++; > + > /* Thermometer: primary service definition */ > sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID); > att_put_u16(THERM_HUMIDITY_SVC_UUID,&atval[0]); > @@ -116,7 +125,8 @@ static int register_attributes(void) > /* Thermometer: Include */ > att_put_u16(0x0550,&atval[0]); > att_put_u16(0x0568,&atval[2]); > - attrib_db_add(0x0202,&uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 4); > + att_put_u16(VENDOR_SPECIFIC_SVC_UUID,&atval[4]); > + attrib_db_add(0x0202,&uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6); > > /* Thermometer: temperature characteristic */ > sdp_uuid16_create(&uuid, GATT_CHARAC_UUID); > @@ -173,6 +183,11 @@ static int register_attributes(void) > strncpy((char *) atval, desc_out_hum, len); > attrib_db_add(0x0214,&uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len); > > + /* Add an SDP record for the above service */ > + sdp_handles[i] = attrib_create_sdp(0x0200, "Thermometer"); > + if (sdp_handles[i]) > + i++; > + > /* Secondary Service: Manufacturer Service */ > sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID); > att_put_u16(MANUFACTURER_SVC_UUID,&atval[0]); > @@ -299,6 +314,11 @@ static int register_attributes(void) > strncpy((char *) atval, desc_weight, len); > attrib_db_add(0x0685,&uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len); > > + /* Add an SDP record for the above service */ > + sdp_handles[i] = attrib_create_sdp(0x0680, "Weight Service"); > + if (sdp_handles[i]) > + i++; > + > return 0; > } > > @@ -309,4 +329,11 @@ int server_example_init(void) > > void server_example_exit(void) > { > + int i; > + > + for (i = 0; i< SDP_RECORD_COUNT; i++) > + if (sdp_handles[i]) { > + attrib_free_sdp(sdp_handles[i]); > + sdp_handles[i] = 0; > + } > } > diff --git a/src/attrib-server.c b/src/attrib-server.c > index 85b39a8..c6438bd 100644 > --- a/src/attrib-server.c > +++ b/src/attrib-server.c > @@ -70,7 +70,8 @@ struct group_elem { > static GIOChannel *l2cap_io = NULL; > static GIOChannel *le_io = NULL; > static GSList *clients = NULL; > -static uint32_t sdp_handle = 0; > +static uint32_t gatt_sdp_handle = 0; > +static uint32_t gap_sdp_handle = 0; > > static uuid_t prim_uuid = { > .type = SDP_UUID16, > @@ -81,14 +82,19 @@ static uuid_t snd_uuid = { > .value.uuid16 = GATT_SND_SVC_UUID > }; > > -static sdp_record_t *server_record_new(void) > +static sdp_record_t *server_record_new(uuid_t *uuid, uint16_t start, uint16_t end) > { > - sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto; > + sdp_list_t *svclass_id, *apseq, *proto[2], *root, *aproto; > uuid_t root_uuid, proto_uuid, gatt_uuid, l2cap; > - sdp_profile_desc_t profile; > sdp_record_t *record; > sdp_data_t *psm, *sh, *eh; > - uint16_t lp = GATT_PSM, start = 0x0001, end = 0xffff; > + uint16_t lp = GATT_PSM; > + > + if (uuid == NULL) > + return NULL; > + > + if (start> end) > + return NULL; > > record = sdp_record_alloc(); > if (record == NULL) > @@ -99,17 +105,10 @@ static sdp_record_t *server_record_new(void) > sdp_set_browse_groups(record, root); > sdp_list_free(root, NULL); > > - sdp_uuid16_create(&gatt_uuid, GENERIC_ATTRIB_SVCLASS_ID); > - svclass_id = sdp_list_append(NULL,&gatt_uuid); > + svclass_id = sdp_list_append(NULL, uuid); > sdp_set_service_classes(record, svclass_id); > sdp_list_free(svclass_id, NULL); > > - sdp_uuid16_create(&profile.uuid, GENERIC_ATTRIB_PROFILE_ID); > - profile.version = 0x0100; > - profiles = sdp_list_append(NULL,&profile); > - sdp_set_profile_descs(record, profiles); > - sdp_list_free(profiles, NULL); > - > sdp_uuid16_create(&l2cap, L2CAP_UUID); > proto[0] = sdp_list_append(NULL,&l2cap); > psm = sdp_data_alloc(SDP_UINT16,&lp); > @@ -127,11 +126,6 @@ static sdp_record_t *server_record_new(void) > aproto = sdp_list_append(NULL, apseq); > sdp_set_access_protos(record, aproto); > > - sdp_set_info_attr(record, "Generic Attribute Profile", "BlueZ", NULL); > - > - sdp_set_url_attr(record, "http://www.bluez.org/", > - "http://www.bluez.org/", "http://www.bluez.org/"); > - > sdp_set_service_id(record, gatt_uuid); > > sdp_data_free(psm); > @@ -176,6 +170,40 @@ static uint8_t att_check_reqs(struct gatt_channel *channel, uint8_t opcode, > return 0; > } > > +static struct attribute *find_primary_range(uint16_t start, uint16_t *end) > +{ > + struct attribute *a, *attrib = NULL; > + GSList *l; > + gboolean found = FALSE; > + > + if (end == NULL) > + return NULL; > + > + for (l = database; l; l = l->next) { > + a = l->data; > + > + if (a->handle< start) > + continue; > + > + if ((a->handle == start)&& > + sdp_uuid_cmp(&a->uuid,&prim_uuid) == 0) { > + found = TRUE; > + *end = start; > + attrib = a; > + continue; > + } else if (!found) > + break; > + > + if (sdp_uuid_cmp(&a->uuid,&prim_uuid) == 0 || > + sdp_uuid_cmp(&a->uuid,&snd_uuid) == 0) > + break; > + else > + *end = a->handle; > + } > + > + return attrib; > +} > + > static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start, > uint16_t end, uuid_t *uuid, > uint8_t *pdu, int len) > @@ -607,7 +635,7 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle, > static uint16_t mtu_exchange(struct gatt_channel *channel, uint16_t mtu, > uint8_t *pdu, int len) > { > - channel->mtu = MIN(mtu, ATT_MAX_MTU); > + channel->mtu = MIN(mtu, channel->mtu); > > return enc_mtu_resp(channel->mtu, pdu, len); > } > @@ -794,7 +822,7 @@ static void confirm_event(GIOChannel *io, void *user_data) > return; > } > > -static void register_core_services(void) > +static gboolean register_core_services(void) > { > uint8_t atval[256]; > uuid_t uuid; > @@ -820,17 +848,37 @@ static void register_core_services(void) > > /* TODO: Implement Appearance characteristic. It is mandatory for > * Peripheral/Central GAP roles. */ > + gap_sdp_handle = attrib_create_sdp(0x0001, "Generic Access Profile"); > + > + if (gap_sdp_handle == 0) { > + error("Failed to register GAP service record"); > + goto failed; > + } > > /* GATT service: primary service definition */ > sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID); > att_put_u16(GENERIC_ATTRIB_PROFILE_ID,&atval[0]); > attrib_db_add(0x0010,&uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2); > + > + gatt_sdp_handle = attrib_create_sdp(0x0010, > + "Generic Attribute Profile"); > + if (gatt_sdp_handle == 0) { > + error("Failed to register GATT service record"); > + goto failed; > + } > + > + return TRUE; > + > +failed: > + if (gap_sdp_handle) > + remove_record_from_server(gap_sdp_handle); > + > + return FALSE; > } > > int attrib_server_init(void) > { > GError *gerr = NULL; > - sdp_record_t *record; > > /* BR/EDR socket */ > l2cap_io = bt_io_listen(BT_IO_L2CAP, NULL, confirm_event, > @@ -846,21 +894,8 @@ int attrib_server_init(void) > return -1; > } > > - record = server_record_new(); > - if (record == NULL) { > - error("Unable to create GATT service record"); > + if (!register_core_services()) > goto failed; > - } > - > - if (add_record_to_server(BDADDR_ANY, record)< 0) { > - error("Failed to register GATT service record"); > - sdp_record_free(record); > - goto failed; > - } > - > - sdp_handle = record->handle; > - > - register_core_services(); > > if (!main_opts.le) > return 0; > @@ -919,8 +954,61 @@ void attrib_server_exit(void) > > g_slist_free(clients); > > - if (sdp_handle) > - remove_record_from_server(sdp_handle); > + if (gatt_sdp_handle) > + remove_record_from_server(gatt_sdp_handle); > + > + if (gap_sdp_handle) > + remove_record_from_server(gap_sdp_handle); > +} > + > +uint32_t attrib_create_sdp(uint16_t handle, const char *name) > +{ > + sdp_record_t *record; > + struct attribute *a; > + uint16_t end = 0; > + uuid_t svc; > + > + a = find_primary_range(handle,&end); > + > + if (a == NULL) > + goto failed; > + > + if (a->len == 2) { > + svc.type = SDP_UUID16; > + svc.value.uuid16 = att_get_u16(a->data); > + } else if (a->len == 16) { > + svc.type = SDP_UUID128; > + memcpy(&svc.value.uuid128, a->data, sizeof(uint128_t)); > + } else > + goto failed; > + > + record = server_record_new(&svc, handle, end); > + > + if (record == NULL) > + goto failed; > + > + if (name) > + sdp_set_info_attr(record, name, "BlueZ", NULL); > + > + if (svc.type == SDP_UUID16&& > + svc.value.uuid16 == GENERIC_ACCESS_PROFILE_ID) { > + sdp_set_url_attr(record, "http://www.bluez.org/", > + "http://www.bluez.org/", > + "http://www.bluez.org/"); > + } > + > + if (add_record_to_server(BDADDR_ANY, record)< 0) > + sdp_record_free(record); > + else > + return record->handle; > + > +failed: > + return 0; > +} > + > +void attrib_free_sdp(uint32_t sdp_handle) > +{ > + remove_record_from_server(sdp_handle); > } > > int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs, > diff --git a/src/attrib-server.h b/src/attrib-server.h > index ba90ff4..34236e4 100644 > --- a/src/attrib-server.h > +++ b/src/attrib-server.h > @@ -30,3 +30,5 @@ int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs, > int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value, > int len); > int attrib_db_del(uint16_t handle); > +uint32_t attrib_create_sdp(uint16_t handle, const char *name); > +void attrib_free_sdp(uint32_t sdp_handle); -- Brian Gix bgix@codeaurora.org Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2011-02-18 20:20 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-02-18 20:11 [PATCH 0/1] SDP registration of Primary GATT Services Brian Gix 2011-02-18 20:11 ` [PATCH 1/1] Add SDP registration of Primary GATT services Brian Gix 2011-02-18 20:20 ` Brian Gix
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).