btgatt-server.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * BlueZ - Bluetooth protocol stack for Linux
  4. *
  5. * Copyright (C) 2014 Google Inc.
  6. *
  7. *
  8. */
  9. #ifdef HAVE_CONFIG_H
  10. #include <config.h>
  11. #endif
  12. #define _GNU_SOURCE
  13. #include <stdio.h>
  14. #include <stdbool.h>
  15. #include <stdint.h>
  16. #include <time.h>
  17. #include <stdlib.h>
  18. #include <getopt.h>
  19. #include <unistd.h>
  20. #include <errno.h>
  21. #include "lib/bluetooth.h"
  22. #include "lib/hci.h"
  23. #include "lib/hci_lib.h"
  24. #include "lib/l2cap.h"
  25. #include "lib/uuid.h"
  26. #include "src/shared/mainloop.h"
  27. #include "src/shared/util.h"
  28. #include "src/shared/att.h"
  29. #include "src/shared/queue.h"
  30. #include "src/shared/timeout.h"
  31. #include "src/shared/gatt-db.h"
  32. #include "src/shared/gatt-server.h"
  33. #define UUID_GAP 0x1800
  34. #define UUID_GATT 0x1801
  35. #define UUID_HEART_RATE 0x180d
  36. #define UUID_HEART_RATE_MSRMT 0x2a37
  37. #define UUID_HEART_RATE_BODY 0x2a38
  38. #define UUID_HEART_RATE_CTRL 0x2a39
  39. #define ATT_CID 4
  40. #define PRLOG(...) \
  41. do { \
  42. printf(__VA_ARGS__); \
  43. print_prompt(); \
  44. } while (0)
  45. #ifndef MIN
  46. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  47. #endif
  48. #define COLOR_OFF "\x1B[0m"
  49. #define COLOR_RED "\x1B[0;91m"
  50. #define COLOR_GREEN "\x1B[0;92m"
  51. #define COLOR_YELLOW "\x1B[0;93m"
  52. #define COLOR_BLUE "\x1B[0;94m"
  53. #define COLOR_MAGENTA "\x1B[0;95m"
  54. #define COLOR_BOLDGRAY "\x1B[1;30m"
  55. #define COLOR_BOLDWHITE "\x1B[1;37m"
  56. static const char test_device_name[] = "Very Long Test Device Name For Testing "
  57. "ATT Protocol Operations On GATT Server";
  58. static bool verbose = false;
  59. struct server {
  60. int fd;
  61. struct bt_att *att;
  62. struct gatt_db *db;
  63. struct bt_gatt_server *gatt;
  64. uint8_t *device_name;
  65. size_t name_len;
  66. uint16_t gatt_svc_chngd_handle;
  67. bool svc_chngd_enabled;
  68. uint16_t hr_handle;
  69. uint16_t hr_msrmt_handle;
  70. uint16_t hr_energy_expended;
  71. bool hr_visible;
  72. bool hr_msrmt_enabled;
  73. int hr_ee_count;
  74. unsigned int hr_timeout_id;
  75. };
  76. static void print_prompt(void)
  77. {
  78. printf(COLOR_BLUE "[GATT server]" COLOR_OFF "# ");
  79. fflush(stdout);
  80. }
  81. static void att_disconnect_cb(int err, void *user_data)
  82. {
  83. printf("Device disconnected: %s\n", strerror(err));
  84. mainloop_quit();
  85. }
  86. static void att_debug_cb(const char *str, void *user_data)
  87. {
  88. const char *prefix = user_data;
  89. PRLOG(COLOR_BOLDGRAY "%s" COLOR_BOLDWHITE "%s\n" COLOR_OFF, prefix,
  90. str);
  91. }
  92. static void gatt_debug_cb(const char *str, void *user_data)
  93. {
  94. const char *prefix = user_data;
  95. PRLOG(COLOR_GREEN "%s%s\n" COLOR_OFF, prefix, str);
  96. }
  97. static void gap_device_name_read_cb(struct gatt_db_attribute *attrib,
  98. unsigned int id, uint16_t offset,
  99. uint8_t opcode, struct bt_att *att,
  100. void *user_data)
  101. {
  102. struct server *server = user_data;
  103. uint8_t error = 0;
  104. size_t len = 0;
  105. const uint8_t *value = NULL;
  106. PRLOG("GAP Device Name Read called\n");
  107. len = server->name_len;
  108. if (offset > len) {
  109. error = BT_ATT_ERROR_INVALID_OFFSET;
  110. goto done;
  111. }
  112. len -= offset;
  113. value = len ? &server->device_name[offset] : NULL;
  114. done:
  115. gatt_db_attribute_read_result(attrib, id, error, value, len);
  116. }
  117. static void gap_device_name_write_cb(struct gatt_db_attribute *attrib,
  118. unsigned int id, uint16_t offset,
  119. const uint8_t *value, size_t len,
  120. uint8_t opcode, struct bt_att *att,
  121. void *user_data)
  122. {
  123. struct server *server = user_data;
  124. uint8_t error = 0;
  125. PRLOG("GAP Device Name Write called\n");
  126. /* If the value is being completely truncated, clean up and return */
  127. if (!(offset + len)) {
  128. free(server->device_name);
  129. server->device_name = NULL;
  130. server->name_len = 0;
  131. goto done;
  132. }
  133. /* Implement this as a variable length attribute value. */
  134. if (offset > server->name_len) {
  135. error = BT_ATT_ERROR_INVALID_OFFSET;
  136. goto done;
  137. }
  138. if (offset + len != server->name_len) {
  139. uint8_t *name;
  140. name = realloc(server->device_name, offset + len);
  141. if (!name) {
  142. error = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
  143. goto done;
  144. }
  145. server->device_name = name;
  146. server->name_len = offset + len;
  147. }
  148. if (value)
  149. memcpy(server->device_name + offset, value, len);
  150. done:
  151. gatt_db_attribute_write_result(attrib, id, error);
  152. }
  153. static void gap_device_name_ext_prop_read_cb(struct gatt_db_attribute *attrib,
  154. unsigned int id, uint16_t offset,
  155. uint8_t opcode, struct bt_att *att,
  156. void *user_data)
  157. {
  158. uint8_t value[2];
  159. PRLOG("Device Name Extended Properties Read called\n");
  160. value[0] = BT_GATT_CHRC_EXT_PROP_RELIABLE_WRITE;
  161. value[1] = 0;
  162. gatt_db_attribute_read_result(attrib, id, 0, value, sizeof(value));
  163. }
  164. static void gatt_service_changed_cb(struct gatt_db_attribute *attrib,
  165. unsigned int id, uint16_t offset,
  166. uint8_t opcode, struct bt_att *att,
  167. void *user_data)
  168. {
  169. PRLOG("Service Changed Read called\n");
  170. gatt_db_attribute_read_result(attrib, id, 0, NULL, 0);
  171. }
  172. static void gatt_svc_chngd_ccc_read_cb(struct gatt_db_attribute *attrib,
  173. unsigned int id, uint16_t offset,
  174. uint8_t opcode, struct bt_att *att,
  175. void *user_data)
  176. {
  177. struct server *server = user_data;
  178. uint8_t value[2];
  179. PRLOG("Service Changed CCC Read called\n");
  180. value[0] = server->svc_chngd_enabled ? 0x02 : 0x00;
  181. value[1] = 0x00;
  182. gatt_db_attribute_read_result(attrib, id, 0, value, sizeof(value));
  183. }
  184. static void gatt_svc_chngd_ccc_write_cb(struct gatt_db_attribute *attrib,
  185. unsigned int id, uint16_t offset,
  186. const uint8_t *value, size_t len,
  187. uint8_t opcode, struct bt_att *att,
  188. void *user_data)
  189. {
  190. struct server *server = user_data;
  191. uint8_t ecode = 0;
  192. PRLOG("Service Changed CCC Write called\n");
  193. if (!value || len != 2) {
  194. ecode = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
  195. goto done;
  196. }
  197. if (offset) {
  198. ecode = BT_ATT_ERROR_INVALID_OFFSET;
  199. goto done;
  200. }
  201. if (value[0] == 0x00)
  202. server->svc_chngd_enabled = false;
  203. else if (value[0] == 0x02)
  204. server->svc_chngd_enabled = true;
  205. else
  206. ecode = 0x80;
  207. PRLOG("Service Changed Enabled: %s\n",
  208. server->svc_chngd_enabled ? "true" : "false");
  209. done:
  210. gatt_db_attribute_write_result(attrib, id, ecode);
  211. }
  212. static void hr_msrmt_ccc_read_cb(struct gatt_db_attribute *attrib,
  213. unsigned int id, uint16_t offset,
  214. uint8_t opcode, struct bt_att *att,
  215. void *user_data)
  216. {
  217. struct server *server = user_data;
  218. uint8_t value[2];
  219. value[0] = server->hr_msrmt_enabled ? 0x01 : 0x00;
  220. value[1] = 0x00;
  221. gatt_db_attribute_read_result(attrib, id, 0, value, 2);
  222. }
  223. static bool hr_msrmt_cb(void *user_data)
  224. {
  225. struct server *server = user_data;
  226. bool expended_present = !(server->hr_ee_count % 10);
  227. uint16_t len = 2;
  228. uint8_t pdu[4];
  229. uint32_t cur_ee;
  230. pdu[0] = 0x06;
  231. pdu[1] = 90 + (rand() % 40);
  232. if (expended_present) {
  233. pdu[0] |= 0x08;
  234. put_le16(server->hr_energy_expended, pdu + 2);
  235. len += 2;
  236. }
  237. bt_gatt_server_send_notification(server->gatt,
  238. server->hr_msrmt_handle,
  239. pdu, len, false);
  240. cur_ee = server->hr_energy_expended;
  241. server->hr_energy_expended = MIN(UINT16_MAX, cur_ee + 10);
  242. server->hr_ee_count++;
  243. return true;
  244. }
  245. static void update_hr_msrmt_simulation(struct server *server)
  246. {
  247. if (!server->hr_msrmt_enabled || !server->hr_visible) {
  248. timeout_remove(server->hr_timeout_id);
  249. return;
  250. }
  251. server->hr_timeout_id = timeout_add(1000, hr_msrmt_cb, server, NULL);
  252. }
  253. static void hr_msrmt_ccc_write_cb(struct gatt_db_attribute *attrib,
  254. unsigned int id, uint16_t offset,
  255. const uint8_t *value, size_t len,
  256. uint8_t opcode, struct bt_att *att,
  257. void *user_data)
  258. {
  259. struct server *server = user_data;
  260. uint8_t ecode = 0;
  261. if (!value || len != 2) {
  262. ecode = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
  263. goto done;
  264. }
  265. if (offset) {
  266. ecode = BT_ATT_ERROR_INVALID_OFFSET;
  267. goto done;
  268. }
  269. if (value[0] == 0x00)
  270. server->hr_msrmt_enabled = false;
  271. else if (value[0] == 0x01) {
  272. if (server->hr_msrmt_enabled) {
  273. PRLOG("HR Measurement Already Enabled\n");
  274. goto done;
  275. }
  276. server->hr_msrmt_enabled = true;
  277. } else
  278. ecode = 0x80;
  279. PRLOG("HR: Measurement Enabled: %s\n",
  280. server->hr_msrmt_enabled ? "true" : "false");
  281. update_hr_msrmt_simulation(server);
  282. done:
  283. gatt_db_attribute_write_result(attrib, id, ecode);
  284. }
  285. static void hr_control_point_write_cb(struct gatt_db_attribute *attrib,
  286. unsigned int id, uint16_t offset,
  287. const uint8_t *value, size_t len,
  288. uint8_t opcode, struct bt_att *att,
  289. void *user_data)
  290. {
  291. struct server *server = user_data;
  292. uint8_t ecode = 0;
  293. if (!value || len != 1) {
  294. ecode = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
  295. goto done;
  296. }
  297. if (offset) {
  298. ecode = BT_ATT_ERROR_INVALID_OFFSET;
  299. goto done;
  300. }
  301. if (value[0] == 1) {
  302. PRLOG("HR: Energy Expended value reset\n");
  303. server->hr_energy_expended = 0;
  304. }
  305. done:
  306. gatt_db_attribute_write_result(attrib, id, ecode);
  307. }
  308. static void confirm_write(struct gatt_db_attribute *attr, int err,
  309. void *user_data)
  310. {
  311. if (!err)
  312. return;
  313. fprintf(stderr, "Error caching attribute %p - err: %d\n", attr, err);
  314. exit(1);
  315. }
  316. static void populate_gap_service(struct server *server)
  317. {
  318. bt_uuid_t uuid;
  319. struct gatt_db_attribute *service, *tmp;
  320. uint16_t appearance;
  321. /* Add the GAP service */
  322. bt_uuid16_create(&uuid, UUID_GAP);
  323. service = gatt_db_add_service(server->db, &uuid, true, 6);
  324. /*
  325. * Device Name characteristic. Make the value dynamically read and
  326. * written via callbacks.
  327. */
  328. bt_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
  329. gatt_db_service_add_characteristic(service, &uuid,
  330. BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
  331. BT_GATT_CHRC_PROP_READ |
  332. BT_GATT_CHRC_PROP_EXT_PROP,
  333. gap_device_name_read_cb,
  334. gap_device_name_write_cb,
  335. server);
  336. bt_uuid16_create(&uuid, GATT_CHARAC_EXT_PROPER_UUID);
  337. gatt_db_service_add_descriptor(service, &uuid, BT_ATT_PERM_READ,
  338. gap_device_name_ext_prop_read_cb,
  339. NULL, server);
  340. /*
  341. * Appearance characteristic. Reads and writes should obtain the value
  342. * from the database.
  343. */
  344. bt_uuid16_create(&uuid, GATT_CHARAC_APPEARANCE);
  345. tmp = gatt_db_service_add_characteristic(service, &uuid,
  346. BT_ATT_PERM_READ,
  347. BT_GATT_CHRC_PROP_READ,
  348. NULL, NULL, server);
  349. /*
  350. * Write the appearance value to the database, since we're not using a
  351. * callback.
  352. */
  353. put_le16(128, &appearance);
  354. gatt_db_attribute_write(tmp, 0, (void *) &appearance,
  355. sizeof(appearance),
  356. BT_ATT_OP_WRITE_REQ,
  357. NULL, confirm_write,
  358. NULL);
  359. gatt_db_service_set_active(service, true);
  360. }
  361. static void populate_gatt_service(struct server *server)
  362. {
  363. bt_uuid_t uuid;
  364. struct gatt_db_attribute *service, *svc_chngd;
  365. /* Add the GATT service */
  366. bt_uuid16_create(&uuid, UUID_GATT);
  367. service = gatt_db_add_service(server->db, &uuid, true, 4);
  368. bt_uuid16_create(&uuid, GATT_CHARAC_SERVICE_CHANGED);
  369. svc_chngd = gatt_db_service_add_characteristic(service, &uuid,
  370. BT_ATT_PERM_READ,
  371. BT_GATT_CHRC_PROP_READ | BT_GATT_CHRC_PROP_INDICATE,
  372. gatt_service_changed_cb,
  373. NULL, server);
  374. server->gatt_svc_chngd_handle = gatt_db_attribute_get_handle(svc_chngd);
  375. bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
  376. gatt_db_service_add_descriptor(service, &uuid,
  377. BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
  378. gatt_svc_chngd_ccc_read_cb,
  379. gatt_svc_chngd_ccc_write_cb, server);
  380. gatt_db_service_set_active(service, true);
  381. }
  382. static void populate_hr_service(struct server *server)
  383. {
  384. bt_uuid_t uuid;
  385. struct gatt_db_attribute *service, *hr_msrmt, *body;
  386. uint8_t body_loc = 1; /* "Chest" */
  387. /* Add Heart Rate Service */
  388. bt_uuid16_create(&uuid, UUID_HEART_RATE);
  389. service = gatt_db_add_service(server->db, &uuid, true, 8);
  390. server->hr_handle = gatt_db_attribute_get_handle(service);
  391. /* HR Measurement Characteristic */
  392. bt_uuid16_create(&uuid, UUID_HEART_RATE_MSRMT);
  393. hr_msrmt = gatt_db_service_add_characteristic(service, &uuid,
  394. BT_ATT_PERM_NONE,
  395. BT_GATT_CHRC_PROP_NOTIFY,
  396. NULL, NULL, NULL);
  397. server->hr_msrmt_handle = gatt_db_attribute_get_handle(hr_msrmt);
  398. bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
  399. gatt_db_service_add_descriptor(service, &uuid,
  400. BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
  401. hr_msrmt_ccc_read_cb,
  402. hr_msrmt_ccc_write_cb, server);
  403. /*
  404. * Body Sensor Location Characteristic. Make reads obtain the value from
  405. * the database.
  406. */
  407. bt_uuid16_create(&uuid, UUID_HEART_RATE_BODY);
  408. body = gatt_db_service_add_characteristic(service, &uuid,
  409. BT_ATT_PERM_READ,
  410. BT_GATT_CHRC_PROP_READ,
  411. NULL, NULL, server);
  412. gatt_db_attribute_write(body, 0, (void *) &body_loc, sizeof(body_loc),
  413. BT_ATT_OP_WRITE_REQ,
  414. NULL, confirm_write,
  415. NULL);
  416. /* HR Control Point Characteristic */
  417. bt_uuid16_create(&uuid, UUID_HEART_RATE_CTRL);
  418. gatt_db_service_add_characteristic(service, &uuid,
  419. BT_ATT_PERM_WRITE,
  420. BT_GATT_CHRC_PROP_WRITE,
  421. NULL, hr_control_point_write_cb,
  422. server);
  423. if (server->hr_visible)
  424. gatt_db_service_set_active(service, true);
  425. }
  426. static void populate_db(struct server *server)
  427. {
  428. populate_gap_service(server);
  429. populate_gatt_service(server);
  430. populate_hr_service(server);
  431. }
  432. static struct server *server_create(int fd, uint16_t mtu, bool hr_visible)
  433. {
  434. struct server *server;
  435. size_t name_len = strlen(test_device_name);
  436. server = new0(struct server, 1);
  437. if (!server) {
  438. fprintf(stderr, "Failed to allocate memory for server\n");
  439. return NULL;
  440. }
  441. server->att = bt_att_new(fd, false);
  442. if (!server->att) {
  443. fprintf(stderr, "Failed to initialze ATT transport layer\n");
  444. goto fail;
  445. }
  446. if (!bt_att_set_close_on_unref(server->att, true)) {
  447. fprintf(stderr, "Failed to set up ATT transport layer\n");
  448. goto fail;
  449. }
  450. if (!bt_att_register_disconnect(server->att, att_disconnect_cb, NULL,
  451. NULL)) {
  452. fprintf(stderr, "Failed to set ATT disconnect handler\n");
  453. goto fail;
  454. }
  455. server->name_len = name_len + 1;
  456. server->device_name = malloc(name_len + 1);
  457. if (!server->device_name) {
  458. fprintf(stderr, "Failed to allocate memory for device name\n");
  459. goto fail;
  460. }
  461. memcpy(server->device_name, test_device_name, name_len);
  462. server->device_name[name_len] = '\0';
  463. server->fd = fd;
  464. server->db = gatt_db_new();
  465. if (!server->db) {
  466. fprintf(stderr, "Failed to create GATT database\n");
  467. goto fail;
  468. }
  469. server->gatt = bt_gatt_server_new(server->db, server->att, mtu, 0);
  470. if (!server->gatt) {
  471. fprintf(stderr, "Failed to create GATT server\n");
  472. goto fail;
  473. }
  474. server->hr_visible = hr_visible;
  475. if (verbose) {
  476. bt_att_set_debug(server->att, BT_ATT_DEBUG_VERBOSE,
  477. att_debug_cb, "att: ", NULL);
  478. bt_gatt_server_set_debug(server->gatt, gatt_debug_cb,
  479. "server: ", NULL);
  480. }
  481. /* Random seed for generating fake Heart Rate measurements */
  482. srand(time(NULL));
  483. /* bt_gatt_server already holds a reference */
  484. populate_db(server);
  485. return server;
  486. fail:
  487. gatt_db_unref(server->db);
  488. free(server->device_name);
  489. bt_att_unref(server->att);
  490. free(server);
  491. return NULL;
  492. }
  493. static void server_destroy(struct server *server)
  494. {
  495. timeout_remove(server->hr_timeout_id);
  496. bt_gatt_server_unref(server->gatt);
  497. gatt_db_unref(server->db);
  498. }
  499. static void usage(void)
  500. {
  501. printf("btgatt-server\n");
  502. printf("Usage:\n\tbtgatt-server [options]\n");
  503. printf("Options:\n"
  504. "\t-i, --index <id>\t\tSpecify adapter index, e.g. hci0\n"
  505. "\t-m, --mtu <mtu>\t\t\tThe ATT MTU to use\n"
  506. "\t-s, --security-level <sec>\tSet security level (low|"
  507. "medium|high)\n"
  508. "\t-t, --type [random|public] \t The source address type\n"
  509. "\t-v, --verbose\t\t\tEnable extra logging\n"
  510. "\t-r, --heart-rate\t\tEnable Heart Rate service\n"
  511. "\t-h, --help\t\t\tDisplay help\n");
  512. }
  513. static struct option main_options[] = {
  514. { "index", 1, 0, 'i' },
  515. { "mtu", 1, 0, 'm' },
  516. { "security-level", 1, 0, 's' },
  517. { "type", 1, 0, 't' },
  518. { "verbose", 0, 0, 'v' },
  519. { "heart-rate", 0, 0, 'r' },
  520. { "help", 0, 0, 'h' },
  521. { }
  522. };
  523. static int l2cap_le_att_listen_and_accept(bdaddr_t *src, int sec,
  524. uint8_t src_type)
  525. {
  526. int sk, nsk;
  527. struct sockaddr_l2 srcaddr, addr;
  528. socklen_t optlen;
  529. struct bt_security btsec;
  530. char ba[18];
  531. sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
  532. if (sk < 0) {
  533. perror("Failed to create L2CAP socket");
  534. return -1;
  535. }
  536. /* Set up source address */
  537. memset(&srcaddr, 0, sizeof(srcaddr));
  538. srcaddr.l2_family = AF_BLUETOOTH;
  539. srcaddr.l2_cid = htobs(ATT_CID);
  540. srcaddr.l2_bdaddr_type = src_type;
  541. bacpy(&srcaddr.l2_bdaddr, src);
  542. if (bind(sk, (struct sockaddr *) &srcaddr, sizeof(srcaddr)) < 0) {
  543. perror("Failed to bind L2CAP socket");
  544. goto fail;
  545. }
  546. /* Set the security level */
  547. memset(&btsec, 0, sizeof(btsec));
  548. btsec.level = sec;
  549. if (setsockopt(sk, SOL_BLUETOOTH, BT_SECURITY, &btsec,
  550. sizeof(btsec)) != 0) {
  551. fprintf(stderr, "Failed to set L2CAP security level\n");
  552. goto fail;
  553. }
  554. if (listen(sk, 10) < 0) {
  555. perror("Listening on socket failed");
  556. goto fail;
  557. }
  558. printf("Started listening on ATT channel. Waiting for connections\n");
  559. memset(&addr, 0, sizeof(addr));
  560. optlen = sizeof(addr);
  561. nsk = accept(sk, (struct sockaddr *) &addr, &optlen);
  562. if (nsk < 0) {
  563. perror("Accept failed");
  564. goto fail;
  565. }
  566. ba2str(&addr.l2_bdaddr, ba);
  567. printf("Connect from %s\n", ba);
  568. close(sk);
  569. return nsk;
  570. fail:
  571. close(sk);
  572. return -1;
  573. }
  574. static void notify_usage(void)
  575. {
  576. printf("Usage: notify [options] <value_handle> <value>\n"
  577. "Options:\n"
  578. "\t -i, --indicate\tSend indication\n"
  579. "e.g.:\n"
  580. "\tnotify 0x0001 00 01 00\n");
  581. }
  582. static struct option notify_options[] = {
  583. { "indicate", 0, 0, 'i' },
  584. { }
  585. };
  586. static bool parse_args(char *str, int expected_argc, char **argv, int *argc)
  587. {
  588. char **ap;
  589. for (ap = argv; (*ap = strsep(&str, " \t")) != NULL;) {
  590. if (**ap == '\0')
  591. continue;
  592. (*argc)++;
  593. ap++;
  594. if (*argc > expected_argc)
  595. return false;
  596. }
  597. return true;
  598. }
  599. static void conf_cb(void *user_data)
  600. {
  601. PRLOG("Received confirmation\n");
  602. }
  603. static void cmd_notify(struct server *server, char *cmd_str)
  604. {
  605. int opt, i;
  606. char *argvbuf[516];
  607. char **argv = argvbuf;
  608. int argc = 1;
  609. uint16_t handle;
  610. char *endptr = NULL;
  611. int length;
  612. uint8_t *value = NULL;
  613. bool indicate = false;
  614. if (!parse_args(cmd_str, 514, argv + 1, &argc)) {
  615. printf("Too many arguments\n");
  616. notify_usage();
  617. return;
  618. }
  619. optind = 0;
  620. argv[0] = "notify";
  621. while ((opt = getopt_long(argc, argv, "+i", notify_options,
  622. NULL)) != -1) {
  623. switch (opt) {
  624. case 'i':
  625. indicate = true;
  626. break;
  627. default:
  628. notify_usage();
  629. return;
  630. }
  631. }
  632. argc -= optind;
  633. argv += optind;
  634. if (argc < 1) {
  635. notify_usage();
  636. return;
  637. }
  638. handle = strtol(argv[0], &endptr, 16);
  639. if (!endptr || *endptr != '\0' || !handle) {
  640. printf("Invalid handle: %s\n", argv[0]);
  641. return;
  642. }
  643. length = argc - 1;
  644. if (length > 0) {
  645. if (length > UINT16_MAX) {
  646. printf("Value too long\n");
  647. return;
  648. }
  649. value = malloc(length);
  650. if (!value) {
  651. printf("Failed to construct value\n");
  652. return;
  653. }
  654. for (i = 1; i < argc; i++) {
  655. if (strlen(argv[i]) != 2) {
  656. printf("Invalid value byte: %s\n",
  657. argv[i]);
  658. goto done;
  659. }
  660. value[i-1] = strtol(argv[i], &endptr, 16);
  661. if (endptr == argv[i] || *endptr != '\0'
  662. || errno == ERANGE) {
  663. printf("Invalid value byte: %s\n",
  664. argv[i]);
  665. goto done;
  666. }
  667. }
  668. }
  669. if (indicate) {
  670. if (!bt_gatt_server_send_indication(server->gatt, handle,
  671. value, length,
  672. conf_cb, NULL, NULL))
  673. printf("Failed to initiate indication\n");
  674. } else if (!bt_gatt_server_send_notification(server->gatt, handle,
  675. value, length, false))
  676. printf("Failed to initiate notification\n");
  677. done:
  678. free(value);
  679. }
  680. static void heart_rate_usage(void)
  681. {
  682. printf("Usage: heart-rate on|off\n");
  683. }
  684. static void cmd_heart_rate(struct server *server, char *cmd_str)
  685. {
  686. bool enable;
  687. uint8_t pdu[4];
  688. struct gatt_db_attribute *attr;
  689. if (!cmd_str) {
  690. heart_rate_usage();
  691. return;
  692. }
  693. if (strcmp(cmd_str, "on") == 0)
  694. enable = true;
  695. else if (strcmp(cmd_str, "off") == 0)
  696. enable = false;
  697. else {
  698. heart_rate_usage();
  699. return;
  700. }
  701. if (enable == server->hr_visible) {
  702. printf("Heart Rate Service already %s\n",
  703. enable ? "visible" : "hidden");
  704. return;
  705. }
  706. server->hr_visible = enable;
  707. attr = gatt_db_get_attribute(server->db, server->hr_handle);
  708. gatt_db_service_set_active(attr, server->hr_visible);
  709. update_hr_msrmt_simulation(server);
  710. if (!server->svc_chngd_enabled)
  711. return;
  712. put_le16(server->hr_handle, pdu);
  713. put_le16(server->hr_handle + 7, pdu + 2);
  714. server->hr_msrmt_enabled = false;
  715. update_hr_msrmt_simulation(server);
  716. bt_gatt_server_send_indication(server->gatt,
  717. server->gatt_svc_chngd_handle,
  718. pdu, 4, conf_cb, NULL, NULL);
  719. }
  720. static void print_uuid(const bt_uuid_t *uuid)
  721. {
  722. char uuid_str[MAX_LEN_UUID_STR];
  723. bt_uuid_t uuid128;
  724. bt_uuid_to_uuid128(uuid, &uuid128);
  725. bt_uuid_to_string(&uuid128, uuid_str, sizeof(uuid_str));
  726. printf("%s\n", uuid_str);
  727. }
  728. static void print_incl(struct gatt_db_attribute *attr, void *user_data)
  729. {
  730. struct server *server = user_data;
  731. uint16_t handle, start, end;
  732. struct gatt_db_attribute *service;
  733. bt_uuid_t uuid;
  734. if (!gatt_db_attribute_get_incl_data(attr, &handle, &start, &end))
  735. return;
  736. service = gatt_db_get_attribute(server->db, start);
  737. if (!service)
  738. return;
  739. gatt_db_attribute_get_service_uuid(service, &uuid);
  740. printf("\t " COLOR_GREEN "include" COLOR_OFF " - handle: "
  741. "0x%04x, - start: 0x%04x, end: 0x%04x,"
  742. "uuid: ", handle, start, end);
  743. print_uuid(&uuid);
  744. }
  745. static void print_desc(struct gatt_db_attribute *attr, void *user_data)
  746. {
  747. printf("\t\t " COLOR_MAGENTA "descr" COLOR_OFF
  748. " - handle: 0x%04x, uuid: ",
  749. gatt_db_attribute_get_handle(attr));
  750. print_uuid(gatt_db_attribute_get_type(attr));
  751. }
  752. static void print_chrc(struct gatt_db_attribute *attr, void *user_data)
  753. {
  754. uint16_t handle, value_handle;
  755. uint8_t properties;
  756. uint16_t ext_prop;
  757. bt_uuid_t uuid;
  758. if (!gatt_db_attribute_get_char_data(attr, &handle,
  759. &value_handle,
  760. &properties,
  761. &ext_prop,
  762. &uuid))
  763. return;
  764. printf("\t " COLOR_YELLOW "charac" COLOR_OFF
  765. " - start: 0x%04x, value: 0x%04x, "
  766. "props: 0x%02x, ext_prop: 0x%04x, uuid: ",
  767. handle, value_handle, properties, ext_prop);
  768. print_uuid(&uuid);
  769. gatt_db_service_foreach_desc(attr, print_desc, NULL);
  770. }
  771. static void print_service(struct gatt_db_attribute *attr, void *user_data)
  772. {
  773. struct server *server = user_data;
  774. uint16_t start, end;
  775. bool primary;
  776. bt_uuid_t uuid;
  777. if (!gatt_db_attribute_get_service_data(attr, &start, &end, &primary,
  778. &uuid))
  779. return;
  780. printf(COLOR_RED "service" COLOR_OFF " - start: 0x%04x, "
  781. "end: 0x%04x, type: %s, uuid: ",
  782. start, end, primary ? "primary" : "secondary");
  783. print_uuid(&uuid);
  784. gatt_db_service_foreach_incl(attr, print_incl, server);
  785. gatt_db_service_foreach_char(attr, print_chrc, NULL);
  786. printf("\n");
  787. }
  788. static void cmd_services(struct server *server, char *cmd_str)
  789. {
  790. gatt_db_foreach_service(server->db, NULL, print_service, server);
  791. }
  792. static bool convert_sign_key(char *optarg, uint8_t key[16])
  793. {
  794. int i;
  795. if (strlen(optarg) != 32) {
  796. printf("sign-key length is invalid\n");
  797. return false;
  798. }
  799. for (i = 0; i < 16; i++) {
  800. if (sscanf(optarg + (i * 2), "%2hhx", &key[i]) != 1)
  801. return false;
  802. }
  803. return true;
  804. }
  805. static void set_sign_key_usage(void)
  806. {
  807. printf("Usage: set-sign-key [options]\nOptions:\n"
  808. "\t -c, --sign-key <remote csrk>\tRemote CSRK\n"
  809. "e.g.:\n"
  810. "\tset-sign-key -c D8515948451FEA320DC05A2E88308188\n");
  811. }
  812. static bool remote_counter(uint32_t *sign_cnt, void *user_data)
  813. {
  814. static uint32_t cnt = 0;
  815. if (*sign_cnt < cnt)
  816. return false;
  817. cnt = *sign_cnt;
  818. return true;
  819. }
  820. static void cmd_set_sign_key(struct server *server, char *cmd_str)
  821. {
  822. char *argv[3];
  823. int argc = 0;
  824. uint8_t key[16];
  825. memset(key, 0, 16);
  826. if (!parse_args(cmd_str, 2, argv, &argc)) {
  827. set_sign_key_usage();
  828. return;
  829. }
  830. if (argc != 2) {
  831. set_sign_key_usage();
  832. return;
  833. }
  834. if (!strcmp(argv[0], "-c") || !strcmp(argv[0], "--sign-key")) {
  835. if (convert_sign_key(argv[1], key))
  836. bt_att_set_remote_key(server->att, key, remote_counter,
  837. server);
  838. } else
  839. set_sign_key_usage();
  840. }
  841. static void cmd_help(struct server *server, char *cmd_str);
  842. typedef void (*command_func_t)(struct server *server, char *cmd_str);
  843. static struct {
  844. char *cmd;
  845. command_func_t func;
  846. char *doc;
  847. } command[] = {
  848. { "help", cmd_help, "\tDisplay help message" },
  849. { "notify", cmd_notify, "\tSend handle-value notification" },
  850. { "heart-rate", cmd_heart_rate, "\tHide/Unhide Heart Rate Service" },
  851. { "services", cmd_services, "\tEnumerate all services" },
  852. { "set-sign-key", cmd_set_sign_key,
  853. "\tSet remote signing key for signed write command"},
  854. { }
  855. };
  856. static void cmd_help(struct server *server, char *cmd_str)
  857. {
  858. int i;
  859. printf("Commands:\n");
  860. for (i = 0; command[i].cmd; i++)
  861. printf("\t%-15s\t%s\n", command[i].cmd, command[i].doc);
  862. }
  863. static void prompt_read_cb(int fd, uint32_t events, void *user_data)
  864. {
  865. ssize_t read;
  866. size_t len = 0;
  867. char *line = NULL;
  868. char *cmd = NULL, *args;
  869. struct server *server = user_data;
  870. int i;
  871. if (events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR)) {
  872. mainloop_quit();
  873. return;
  874. }
  875. read = getline(&line, &len, stdin);
  876. if (read < 0)
  877. return;
  878. if (read <= 1) {
  879. cmd_help(server, NULL);
  880. print_prompt();
  881. return;
  882. }
  883. line[read-1] = '\0';
  884. args = line;
  885. while ((cmd = strsep(&args, " \t")))
  886. if (*cmd != '\0')
  887. break;
  888. if (!cmd)
  889. goto failed;
  890. for (i = 0; command[i].cmd; i++) {
  891. if (strcmp(command[i].cmd, cmd) == 0)
  892. break;
  893. }
  894. if (command[i].cmd)
  895. command[i].func(server, args);
  896. else
  897. fprintf(stderr, "Unknown command: %s\n", line);
  898. failed:
  899. print_prompt();
  900. free(line);
  901. }
  902. static void signal_cb(int signum, void *user_data)
  903. {
  904. switch (signum) {
  905. case SIGINT:
  906. case SIGTERM:
  907. mainloop_quit();
  908. break;
  909. default:
  910. break;
  911. }
  912. }
  913. int main(int argc, char *argv[])
  914. {
  915. int opt;
  916. bdaddr_t src_addr;
  917. int dev_id = -1;
  918. int fd;
  919. int sec = BT_SECURITY_LOW;
  920. uint8_t src_type = BDADDR_LE_PUBLIC;
  921. uint16_t mtu = 0;
  922. bool hr_visible = false;
  923. struct server *server;
  924. while ((opt = getopt_long(argc, argv, "+hvrs:t:m:i:",
  925. main_options, NULL)) != -1) {
  926. switch (opt) {
  927. case 'h':
  928. usage();
  929. return EXIT_SUCCESS;
  930. case 'v':
  931. verbose = true;
  932. break;
  933. case 'r':
  934. hr_visible = true;
  935. break;
  936. case 's':
  937. if (strcmp(optarg, "low") == 0)
  938. sec = BT_SECURITY_LOW;
  939. else if (strcmp(optarg, "medium") == 0)
  940. sec = BT_SECURITY_MEDIUM;
  941. else if (strcmp(optarg, "high") == 0)
  942. sec = BT_SECURITY_HIGH;
  943. else {
  944. fprintf(stderr, "Invalid security level\n");
  945. return EXIT_FAILURE;
  946. }
  947. break;
  948. case 't':
  949. if (strcmp(optarg, "random") == 0)
  950. src_type = BDADDR_LE_RANDOM;
  951. else if (strcmp(optarg, "public") == 0)
  952. src_type = BDADDR_LE_PUBLIC;
  953. else {
  954. fprintf(stderr,
  955. "Allowed types: random, public\n");
  956. return EXIT_FAILURE;
  957. }
  958. break;
  959. case 'm': {
  960. int arg;
  961. arg = atoi(optarg);
  962. if (arg <= 0) {
  963. fprintf(stderr, "Invalid MTU: %d\n", arg);
  964. return EXIT_FAILURE;
  965. }
  966. if (arg > UINT16_MAX) {
  967. fprintf(stderr, "MTU too large: %d\n", arg);
  968. return EXIT_FAILURE;
  969. }
  970. mtu = (uint16_t) arg;
  971. break;
  972. }
  973. case 'i':
  974. dev_id = hci_devid(optarg);
  975. if (dev_id < 0) {
  976. perror("Invalid adapter");
  977. return EXIT_FAILURE;
  978. }
  979. break;
  980. default:
  981. fprintf(stderr, "Invalid option: %c\n", opt);
  982. return EXIT_FAILURE;
  983. }
  984. }
  985. argc -= optind;
  986. argv -= optind;
  987. optind = 0;
  988. if (argc) {
  989. usage();
  990. return EXIT_SUCCESS;
  991. }
  992. if (dev_id == -1)
  993. bacpy(&src_addr, BDADDR_ANY);
  994. else if (hci_devba(dev_id, &src_addr) < 0) {
  995. perror("Adapter not available");
  996. return EXIT_FAILURE;
  997. }
  998. fd = l2cap_le_att_listen_and_accept(&src_addr, sec, src_type);
  999. if (fd < 0) {
  1000. fprintf(stderr, "Failed to accept L2CAP ATT connection\n");
  1001. return EXIT_FAILURE;
  1002. }
  1003. mainloop_init();
  1004. server = server_create(fd, mtu, hr_visible);
  1005. if (!server) {
  1006. close(fd);
  1007. return EXIT_FAILURE;
  1008. }
  1009. if (mainloop_add_fd(fileno(stdin),
  1010. EPOLLIN | EPOLLRDHUP | EPOLLHUP | EPOLLERR,
  1011. prompt_read_cb, server, NULL) < 0) {
  1012. fprintf(stderr, "Failed to initialize console\n");
  1013. server_destroy(server);
  1014. return EXIT_FAILURE;
  1015. }
  1016. printf("Running GATT server\n");
  1017. print_prompt();
  1018. mainloop_run_with_signal(signal_cb, NULL);
  1019. printf("\n\nShutting down...\n");
  1020. server_destroy(server);
  1021. return EXIT_SUCCESS;
  1022. }