From: Brian Gix <bgix@codeaurora.org>
To: linux-bluetooth@vger.kernel.org
Cc: johan.hedberg@nokia.com, padovan@profusion.mobi,
Brian Gix <bgix@codeaurora.org>
Subject: [PATCH 2/3] Add SDP registration of Primary GATT services
Date: Wed, 16 Feb 2011 13:18:00 -0800 [thread overview]
Message-ID: <1297891081-27976-3-git-send-email-bgix@codeaurora.org> (raw)
In-Reply-To: <1297891081-27976-1-git-send-email-bgix@codeaurora.org>
SDP registration can be supressed by passing Zero as the end
handle argument to attrib_db_add().
---
attrib/example.c | 119 +++++++++++++++++++++++++++++++------------
src/attrib-server.c | 139 +++++++++++++++++++++++++++++++++++----------------
src/attrib-server.h | 6 ++-
3 files changed, 184 insertions(+), 80 deletions(-)
diff --git a/attrib/example.c b/attrib/example.c
index 1911912..eab3c0f 100644
--- a/attrib/example.c
+++ b/attrib/example.c
@@ -31,6 +31,7 @@
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
+#include <src/sdpd.h>
#include <glib.h>
@@ -59,6 +60,9 @@
#define FMT_KILOGRAM_UUID 0xA010
#define FMT_HANGING_UUID 0xA011
+#define SDP_RECORD_COUNT 10
+sdp_record_t *sdp_records[SDP_RECORD_COUNT];
+
static int register_attributes(void)
{
const char *desc_out_temp = "Outside Temperature";
@@ -77,59 +81,73 @@ 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);
att_put_u16(BATTERY_STATE_SVC_UUID, &atval[0]);
- attrib_db_add(0x0100, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+ sdp_records[i++] = attrib_db_add(0x0100, 0x0111, &uuid,
+ "Battery State Service",
+ ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 2);
/* Battery: battery state characteristic */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0110, &atval[1]);
att_put_u16(BATTERY_STATE_UUID, &atval[3]);
- attrib_db_add(0x0106, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0106, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Battery: battery state attribute */
sdp_uuid16_create(&uuid, BATTERY_STATE_UUID);
atval[0] = 0x04;
- attrib_db_add(0x0110, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);
+ attrib_db_add(0x0110, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 1);
/* Battery: Client Characteristic Configuration */
sdp_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
atval[0] = 0x00;
atval[1] = 0x00;
- attrib_db_add(0x0111, &uuid, ATT_NONE, ATT_AUTHENTICATION, atval, 2);
+ attrib_db_add(0x0111, 0, &uuid, NULL, ATT_NONE, ATT_AUTHENTICATION,
+ atval, 2);
/* Thermometer: primary service definition */
sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
att_put_u16(THERM_HUMIDITY_SVC_UUID, &atval[0]);
- attrib_db_add(0x0200, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+ sdp_records[i++] = attrib_db_add(0x0200, 0x0214, &uuid, "Thermometer",
+ ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 2);
/* Thermometer: Include */
sdp_uuid16_create(&uuid, GATT_INCLUDE_UUID);
att_put_u16(0x0500, &atval[0]);
att_put_u16(0x0504, &atval[2]);
att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
- attrib_db_add(0x0201, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
+ attrib_db_add(0x0201, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 6);
/* 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, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 6);
/* Thermometer: temperature characteristic */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0204, &atval[1]);
att_put_u16(TEMPERATURE_UUID, &atval[3]);
- attrib_db_add(0x0203, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0203, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Thermometer: temperature characteristic value */
sdp_uuid16_create(&uuid, TEMPERATURE_UUID);
atval[0] = 0x8A;
atval[1] = 0x02;
- attrib_db_add(0x0204, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+ attrib_db_add(0x0204, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 2);
/* Thermometer: temperature characteristic format */
sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
@@ -138,25 +156,29 @@ static int register_attributes(void)
att_put_u16(FMT_CELSIUS_UUID, &atval[2]);
atval[4] = 0x01;
att_put_u16(FMT_OUTSIDE_UUID, &atval[5]);
- attrib_db_add(0x0205, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 7);
+ attrib_db_add(0x0205, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 7);
/* Thermometer: characteristic user description */
sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
len = strlen(desc_out_temp);
strncpy((char *) atval, desc_out_temp, len);
- attrib_db_add(0x0206, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+ attrib_db_add(0x0206, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, len);
/* Thermometer: relative humidity characteristic */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0212, &atval[1]);
att_put_u16(RELATIVE_HUMIDITY_UUID, &atval[3]);
- attrib_db_add(0x0210, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0210, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Thermometer: relative humidity value */
sdp_uuid16_create(&uuid, RELATIVE_HUMIDITY_UUID);
atval[0] = 0x27;
- attrib_db_add(0x0212, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);
+ attrib_db_add(0x0212, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 1);
/* Thermometer: relative humidity characteristic format */
sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
@@ -165,68 +187,79 @@ static int register_attributes(void)
att_put_u16(FMT_PERCENT_UUID, &atval[2]);
att_put_u16(BLUETOOTH_SIG_UUID, &atval[4]);
att_put_u16(FMT_OUTSIDE_UUID, &atval[6]);
- attrib_db_add(0x0213, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);
+ attrib_db_add(0x0213, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 8);
/* Thermometer: characteristic user description */
sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
len = strlen(desc_out_hum);
strncpy((char *) atval, desc_out_hum, len);
- attrib_db_add(0x0214, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+ attrib_db_add(0x0214, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, len);
/* Secondary Service: Manufacturer Service */
sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
att_put_u16(MANUFACTURER_SVC_UUID, &atval[0]);
- attrib_db_add(0x0500, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+ attrib_db_add(0x0500, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 2);
/* Manufacturer name characteristic definition */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0502, &atval[1]);
att_put_u16(MANUFACTURER_NAME_UUID, &atval[3]);
- attrib_db_add(0x0501, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0501, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Manufacturer name characteristic value */
sdp_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
len = strlen(manufacturer_name1);
strncpy((char *) atval, manufacturer_name1, len);
- attrib_db_add(0x0502, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+ attrib_db_add(0x0502, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, len);
/* Manufacturer serial number characteristic */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0504, &atval[1]);
att_put_u16(MANUFACTURER_SERIAL_UUID, &atval[3]);
- attrib_db_add(0x0503, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0503, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Manufacturer serial number characteristic value */
sdp_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
len = strlen(serial1);
strncpy((char *) atval, serial1, len);
- attrib_db_add(0x0504, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+ attrib_db_add(0x0504, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, len);
/* Secondary Service: Manufacturer Service */
sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
att_put_u16(MANUFACTURER_SVC_UUID, &atval[0]);
- attrib_db_add(0x0505, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+ attrib_db_add(0x0505, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 2);
/* Manufacturer name characteristic definition */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0507, &atval[1]);
att_put_u16(MANUFACTURER_NAME_UUID, &atval[3]);
- attrib_db_add(0x0506, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0506, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Secondary Service: Vendor Specific Service */
sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
att_put_u16(VENDOR_SPECIFIC_SVC_UUID, &atval[0]);
- attrib_db_add(0x0550, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+ attrib_db_add(0x0550, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 2);
/* Vendor Specific Type characteristic definition */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0568, &atval[1]);
att_put_u16(VENDOR_SPECIFIC_TYPE_UUID, &atval[3]);
- attrib_db_add(0x0560, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0560, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Vendor Specific Type characteristic value */
sdp_uuid16_create(&uuid, VENDOR_SPECIFIC_TYPE_UUID);
@@ -236,45 +269,53 @@ static int register_attributes(void)
atval[3] = 0x64;
atval[4] = 0x6F;
atval[5] = 0x72;
- attrib_db_add(0x0568, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
+ attrib_db_add(0x0568, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 6);
/* Manufacturer name attribute */
sdp_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
len = strlen(manufacturer_name2);
strncpy((char *) atval, manufacturer_name2, len);
- attrib_db_add(0x0507, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+ attrib_db_add(0x0507, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, len);
/* Characteristic: serial number */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0509, &atval[1]);
att_put_u16(MANUFACTURER_SERIAL_UUID, &atval[3]);
- attrib_db_add(0x0508, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0508, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Serial number characteristic value */
sdp_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
len = strlen(serial2);
strncpy((char *) atval, serial2, len);
- attrib_db_add(0x0509, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+ attrib_db_add(0x0509, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, len);
/* Weight service: primary service definition */
sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
memcpy(atval, prim_weight_uuid, 16);
- attrib_db_add(0x0680, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 16);
+ sdp_records[i++] = attrib_db_add(0x0680, 0x685, &uuid, "Weight Service",
+ ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 16);
/* Weight: include */
sdp_uuid16_create(&uuid, GATT_INCLUDE_UUID);
att_put_u16(0x0505, &atval[0]);
att_put_u16(0x0509, &atval[2]);
att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
- attrib_db_add(0x0681, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
+ attrib_db_add(0x0681, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 6);
/* Weight: characteristic */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0683, &atval[1]);
memcpy(&atval[3], char_weight_uuid, 16);
- attrib_db_add(0x0682, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 19);
+ attrib_db_add(0x0682, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 19);
/* Weight: characteristic value */
sdp_uuid128_create(&uuid, char_weight_uuid);
@@ -282,7 +323,8 @@ static int register_attributes(void)
atval[1] = 0x55;
atval[2] = 0x00;
atval[3] = 0x00;
- attrib_db_add(0x0683, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 4);
+ attrib_db_add(0x0683, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 4);
/* Weight: characteristic format */
sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
@@ -291,13 +333,15 @@ static int register_attributes(void)
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(0x0684, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);
+ attrib_db_add(0x0684, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 8);
/* Weight: characteristic user description */
sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
len = strlen(desc_weight);
strncpy((char *) atval, desc_weight, len);
- attrib_db_add(0x0685, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+ attrib_db_add(0x0685, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, len);
return 0;
}
@@ -309,4 +353,11 @@ int server_example_init(void)
void server_example_exit(void)
{
+ int i;
+
+ for (i = 0; i < SDP_RECORD_COUNT; i++)
+ if (sdp_records[i]) {
+ remove_record_from_server(sdp_records[i]->handle);
+ sdp_records[i] = NULL;
+ }
}
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 72f5b17..db42ab2 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);
@@ -609,7 +603,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);
}
@@ -796,43 +790,68 @@ 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;
int len;
+ sdp_record_t *record;
/* GAP service: primary service definition */
sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
att_put_u16(GENERIC_ACCESS_PROFILE_ID, &atval[0]);
- attrib_db_add(0x0001, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+ record = attrib_db_add(0x0001, 0x0006, &uuid, "Generic Access Profile",
+ ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
/* GAP service: device name characteristic */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0006, &atval[1]);
att_put_u16(GATT_CHARAC_DEVICE_NAME, &atval[3]);
- attrib_db_add(0x0004, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0004, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* GAP service: device name attribute */
sdp_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
len = strlen(main_opts.name);
- attrib_db_add(0x0006, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
+ attrib_db_add(0x0006, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
(uint8_t *) main_opts.name, len);
/* TODO: Implement Appearance characteristic. It is mandatory for
* Peripheral/Central GAP roles. */
+ if (record == NULL) {
+ error("Failed to register GAP service record");
+ goto failed;
+ }
+
+ gap_sdp_handle = record->handle;
+
/* 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);
+ record = attrib_db_add(0x0010, 0x0010, &uuid, "Generic Attribute Profile",
+ ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+
+ if (record == NULL) {
+ error("Failed to register GATT service record");
+ goto failed;
+ }
+
+ gatt_sdp_handle = record->handle;
+
+ 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,
@@ -848,21 +867,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;
@@ -921,15 +927,60 @@ 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);
}
-int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
- const uint8_t *value, int len)
+sdp_record_t *attrib_db_add(uint16_t handle, uint16_t end, uuid_t *uuid,
+ const char *name,
+ int read_reqs, int write_reqs,
+ const uint8_t *value, int len)
{
struct attribute *a;
+ uuid_t svc;
+ sdp_record_t *record = NULL;
+
+ /* If a valid range is being added AND this is a Primary Service, */
+ /* add it to the SDP database as well. */
+
+ if (end == 0 || handle > end)
+ goto no_sdp;
+
+ if (uuid->type != SDP_UUID16 || uuid->value.uuid16 != GATT_PRIM_SVC_UUID)
+ goto no_sdp;
+
+ if (len == 2) {
+ svc.type = SDP_UUID16;
+ svc.value.uuid16 = att_get_u16(value);
+ } else if (len == 16) {
+ svc.type = SDP_UUID128;
+ memcpy(&svc.value.uuid128, value, sizeof(uint128_t));
+ } else
+ return NULL;
+ record = server_record_new(&svc, handle, end);
+ if (record == NULL)
+ return NULL;
+
+ 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);
+ return NULL;
+ }
+
+no_sdp:
/* FIXME: handle conflicts */
a = g_malloc0(sizeof(struct attribute) + len);
@@ -942,7 +993,7 @@ int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
database = g_slist_insert_sorted(database, a, attribute_cmp);
- return 0;
+ return record;
}
int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
diff --git a/src/attrib-server.h b/src/attrib-server.h
index ba90ff4..2601d0e 100644
--- a/src/attrib-server.h
+++ b/src/attrib-server.h
@@ -25,8 +25,10 @@
int attrib_server_init(void);
void attrib_server_exit(void);
-int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
- const uint8_t *value, int len);
+sdp_record_t *attrib_db_add(uint16_t handle, uint16_t end, uuid_t *uuid,
+ const char *name,
+ int read_reqs, int write_reqs,
+ const uint8_t *value, int len);
int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
int len);
int attrib_db_del(uint16_t 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
next prev parent reply other threads:[~2011-02-16 21:18 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-02-16 21:17 [PATCH 0/3] Modifications composed during UPF38 Brian Gix
2011-02-16 21:17 ` [PATCH 1/3] Fixed def of ATT_UUID per BT Assigned Numbers Brian Gix
2011-02-15 17:08 ` Johan Hedberg
2011-02-16 21:18 ` Brian Gix [this message]
2011-02-14 21:53 ` [PATCH 2/3] Add SDP registration of Primary GATT services Anderson Lizardo
2011-02-16 16:26 ` Brian Gix
2011-02-16 17:00 ` Anderson Lizardo
2011-02-16 21:18 ` [PATCH 3/3] Add gatttool enhancements for UPF Brian Gix
2011-02-14 21:41 ` Anderson Lizardo
2011-02-16 15:53 ` Brian Gix
2011-02-16 16:38 ` Anderson Lizardo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1297891081-27976-3-git-send-email-bgix@codeaurora.org \
--to=bgix@codeaurora.org \
--cc=johan.hedberg@nokia.com \
--cc=linux-bluetooth@vger.kernel.org \
--cc=padovan@profusion.mobi \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).