3
* BlueZ - Bluetooth protocol stack for Linux
5
* Copyright (C) 2010 Nokia Corporation
6
* Copyright (C) 2010 Marcel Holtmann <marcel@holtmann.org>
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30
#include <arpa/inet.h>
32
#include <bluetooth/sdp.h>
33
#include <bluetooth/sdp_lib.h>
38
#include "attrib-server.h"
43
/* FIXME: Not defined by SIG? UUID128? */
44
#define OPCODES_SUPPORTED_UUID 0xA001
45
#define BATTERY_STATE_SVC_UUID 0xA002
46
#define BATTERY_STATE_UUID 0xA003
47
#define THERM_HUMIDITY_SVC_UUID 0xA004
48
#define MANUFACTURER_SVC_UUID 0xA005
49
#define TEMPERATURE_UUID 0xA006
50
#define FMT_CELSIUS_UUID 0xA007
51
#define FMT_OUTSIDE_UUID 0xA008
52
#define RELATIVE_HUMIDITY_UUID 0xA009
53
#define FMT_PERCENT_UUID 0xA00A
54
#define BLUETOOTH_SIG_UUID 0xA00B
55
#define MANUFACTURER_NAME_UUID 0xA00C
56
#define MANUFACTURER_SERIAL_UUID 0xA00D
57
#define VENDOR_SPECIFIC_SVC_UUID 0xA00E
58
#define VENDOR_SPECIFIC_TYPE_UUID 0xA00F
59
#define FMT_KILOGRAM_UUID 0xA010
60
#define FMT_HANGING_UUID 0xA011
62
static guint timeout_id = 0;
64
static gboolean change_battery_state(gpointer user_data)
66
static uint8_t state = 0x05;
70
/* Battery state is being increased every 10 seconds. */
72
sdp_uuid16_create(&uuid, BATTERY_STATE_UUID);
73
attrib_db_update(0x0110, &uuid, atval, 1);
78
static int register_attributes(void)
80
const char *devname = "Example Device";
81
const char *desc_out_temp = "Outside Temperature";
82
const char *desc_out_hum = "Outside Relative Humidity";
83
const char *desc_weight = "Rucksack Weight";
84
const char *manufacturer_name1 = "ACME Temperature Sensor";
85
const char *manufacturer_name2 = "ACME Weighing Scales";
86
const char *serial1 = "237495-3282-A";
87
const char *serial2 = "11267-2327A00239";
88
const unsigned char char_weight_uuid[] = { 0x80, 0x88, 0xF2, 0x18, 0x90,
89
0x2C, 0x45, 0x0B, 0xB6, 0xC4, 0x62, 0x89, 0x1E, 0x8C, 0x25,
91
const unsigned char prim_weight_uuid[] = { 0x4F, 0x0A, 0xC0, 0x96, 0x35,
92
0xD4, 0x49, 0x11, 0x96, 0x31, 0xDE, 0xA8, 0xDC, 0x74, 0xEE,
99
/* GAP service: primary service definition */
100
sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
101
u16 = htons(GENERIC_ACCESS_PROFILE_ID);
104
attrib_db_add(0x0001, &uuid, atval, 2);
106
/* GAP service: device name characteristic */
107
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
108
u16 = htons(GATT_CHARAC_DEVICE_NAME);
109
atval[0] = ATT_CHAR_PROPER_READ;
114
attrib_db_add(0x0004, &uuid, atval, 5);
116
/* GAP service: device name attribute */
117
sdp_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
118
len = strlen(devname);
119
strncpy((char *) atval, devname, len);
120
attrib_db_add(0x0006, &uuid, atval, len);
122
/* GATT service: primary service definition */
123
sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
124
u16 = htons(GENERIC_ATTRIB_PROFILE_ID);
127
attrib_db_add(0x0010, &uuid, atval, 2);
129
/* GATT service: attributes opcodes characteristic */
130
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
131
u16 = htons(OPCODES_SUPPORTED_UUID);
132
atval[0] = ATT_CHAR_PROPER_READ;
137
attrib_db_add(0x0011, &uuid, atval, 5);
139
/* GATT service: attribute opcodes supported */
140
sdp_uuid16_create(&uuid, OPCODES_SUPPORTED_UUID);
143
attrib_db_add(0x0012, &uuid, atval, 2);
145
/* Battery state service: primary service definition */
146
sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
147
u16 = htons(BATTERY_STATE_SVC_UUID);
150
attrib_db_add(0x0100, &uuid, atval, 2);
152
/* Battery: battery state characteristic */
153
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
154
u16 = htons(BATTERY_STATE_UUID);
155
atval[0] = ATT_CHAR_PROPER_READ;
160
attrib_db_add(0x0106, &uuid, atval, 5);
162
/* Battery: battery state attribute */
163
sdp_uuid16_create(&uuid, BATTERY_STATE_UUID);
165
attrib_db_add(0x0110, &uuid, atval, 1);
167
/* Battery: Client Characteristic Configuration */
168
sdp_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
171
attrib_db_add(0x0111, &uuid, atval, 2);
173
timeout_id = g_timeout_add_seconds(10, change_battery_state, NULL);
175
/* Thermometer: primary service definition */
176
sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
177
u16 = htons(THERM_HUMIDITY_SVC_UUID);
180
attrib_db_add(0x0200, &uuid, atval, 2);
182
/* Thermometer: Include */
183
sdp_uuid16_create(&uuid, GATT_INCLUDE_UUID);
184
u16 = htons(MANUFACTURER_SVC_UUID);
191
attrib_db_add(0x0201, &uuid, atval, 6);
193
/* Thermometer: Include */
198
attrib_db_add(0x0202, &uuid, atval, 4);
200
/* Thermometer: temperature characteristic */
201
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
202
u16 = htons(TEMPERATURE_UUID);
203
atval[0] = ATT_CHAR_PROPER_READ;
208
attrib_db_add(0x0203, &uuid, atval, 5);
210
/* Thermometer: temperature characteristic value */
211
sdp_uuid16_create(&uuid, TEMPERATURE_UUID);
214
attrib_db_add(0x0204, &uuid, atval, 2);
216
/* Thermometer: temperature characteristic format */
217
sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
218
u16 = htons(FMT_CELSIUS_UUID);
224
u16 = htons(FMT_OUTSIDE_UUID);
227
attrib_db_add(0x0205, &uuid, atval, 7);
229
/* Thermometer: characteristic user description */
230
sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
231
len = strlen(desc_out_temp);
232
strncpy((char *) atval, desc_out_temp, len);
233
attrib_db_add(0x0206, &uuid, atval, len);
235
/* Thermometer: relative humidity characteristic */
236
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
237
u16 = htons(RELATIVE_HUMIDITY_UUID);
238
atval[0] = ATT_CHAR_PROPER_READ;
243
attrib_db_add(0x0210, &uuid, atval, 5);
245
/* Thermometer: relative humidity value */
246
sdp_uuid16_create(&uuid, RELATIVE_HUMIDITY_UUID);
248
attrib_db_add(0x0212, &uuid, atval, 1);
250
/* Thermometer: relative humidity characteristic format */
251
sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
252
u16 = htons(FMT_PERCENT_UUID);
257
u16 = htons(BLUETOOTH_SIG_UUID);
260
u16 = htons(FMT_OUTSIDE_UUID);
263
attrib_db_add(0x0213, &uuid, atval, 8);
265
/* Thermometer: characteristic user description */
266
sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
267
len = strlen(desc_out_hum);
268
strncpy((char *) atval, desc_out_hum, len);
269
attrib_db_add(0x0214, &uuid, atval, len);
271
/* Secondary Service: Manufacturer Service */
272
sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
273
u16 = htons(MANUFACTURER_SVC_UUID);
276
attrib_db_add(0x0500, &uuid, atval, 2);
278
/* Manufacturer name characteristic definition */
279
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
280
u16 = htons(MANUFACTURER_NAME_UUID);
281
atval[0] = ATT_CHAR_PROPER_READ;
286
attrib_db_add(0x0501, &uuid, atval, 5);
288
/* Manufacturer name characteristic value */
289
sdp_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
290
len = strlen(manufacturer_name1);
291
strncpy((char *) atval, manufacturer_name1, len);
292
attrib_db_add(0x0502, &uuid, atval, len);
294
/* Manufacturer serial number characteristic */
295
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
296
u16 = htons(MANUFACTURER_SERIAL_UUID);
297
atval[0] = ATT_CHAR_PROPER_READ;
302
attrib_db_add(0x0503, &uuid, atval, 5);
304
/* Manufacturer serial number characteristic value */
305
sdp_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
306
len = strlen(serial1);
307
strncpy((char *) atval, serial1, len);
308
attrib_db_add(0x0504, &uuid, atval, len);
310
/* Secondary Service: Manufacturer Service */
311
sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
312
u16 = htons(MANUFACTURER_SVC_UUID);
315
attrib_db_add(0x0505, &uuid, atval, 2);
317
/* Manufacturer name characteristic definition */
318
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
319
u16 = htons(MANUFACTURER_NAME_UUID);
320
atval[0] = ATT_CHAR_PROPER_READ;
325
attrib_db_add(0x0506, &uuid, atval, 5);
327
/* Secondary Service: Vendor Specific Service */
328
sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
329
u16 = htons(VENDOR_SPECIFIC_SVC_UUID);
332
attrib_db_add(0x0550, &uuid, atval, 2);
334
/* Vendor Specific Type characteristic definition */
335
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
336
u16 = htons(VENDOR_SPECIFIC_TYPE_UUID);
337
atval[0] = ATT_CHAR_PROPER_READ;
342
attrib_db_add(0x0560, &uuid, atval, 5);
344
/* Vendor Specific Type characteristic value */
345
sdp_uuid16_create(&uuid, VENDOR_SPECIFIC_TYPE_UUID);
352
attrib_db_add(0x0568, &uuid, atval, 6);
354
/* Manufacturer name attribute */
355
sdp_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
356
len = strlen(manufacturer_name2);
357
strncpy((char *) atval, manufacturer_name2, len);
358
attrib_db_add(0x0507, &uuid, atval, len);
360
/* Characteristic: serial number */
361
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
362
u16 = htons(MANUFACTURER_SERIAL_UUID);
363
atval[0] = ATT_CHAR_PROPER_READ;
368
attrib_db_add(0x0508, &uuid, atval, 5);
370
/* Serial number characteristic value */
371
sdp_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
372
len = strlen(serial2);
373
strncpy((char *) atval, serial2, len);
374
attrib_db_add(0x0509, &uuid, atval, len);
376
/* Weight service: primary service definition */
377
sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
378
memcpy(atval, prim_weight_uuid, 16);
379
attrib_db_add(0x0680, &uuid, atval, 16);
381
/* Weight: include */
382
sdp_uuid16_create(&uuid, GATT_INCLUDE_UUID);
383
u16 = htons(MANUFACTURER_SVC_UUID);
390
attrib_db_add(0x0681, &uuid, atval, 6);
392
/* Weight: characteristic */
393
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
394
atval[0] = ATT_CHAR_PROPER_READ;
397
memcpy(atval + 3, char_weight_uuid, 16);
398
attrib_db_add(0x0682, &uuid, atval, 19);
400
/* Weight: characteristic value */
401
sdp_uuid128_create(&uuid, char_weight_uuid);
406
attrib_db_add(0x0683, &uuid, atval, 4);
408
/* Weight: characteristic format */
409
sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
410
u16 = htons(FMT_KILOGRAM_UUID);
415
u16 = htons(BLUETOOTH_SIG_UUID);
418
u16 = htons(FMT_HANGING_UUID);
421
attrib_db_add(0x0684, &uuid, atval, 8);
423
/* Weight: characteristic user description */
424
sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
425
len = strlen(desc_weight);
426
strncpy((char *) atval, desc_weight, len);
427
attrib_db_add(0x0685, &uuid, atval, len);
432
int server_example_init(void)
434
return register_attributes();
437
void server_example_exit(void)
439
g_source_remove(timeout_id);