gatt.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2015 Intel Corporation. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #include <stdio.h>
  14. #include <unistd.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <sys/epoll.h>
  18. #include "lib/bluetooth.h"
  19. #include "lib/l2cap.h"
  20. #include "lib/uuid.h"
  21. #include "src/shared/mainloop.h"
  22. #include "src/shared/util.h"
  23. #include "src/shared/queue.h"
  24. #include "src/shared/att.h"
  25. #include "src/shared/gatt-db.h"
  26. #include "src/shared/gatt-server.h"
  27. #include "src/shared/gatt-client.h"
  28. #include "peripheral/gatt.h"
  29. #define ATT_CID 4
  30. #define UUID_GAP 0x1800
  31. struct gatt_conn {
  32. struct bt_att *att;
  33. struct bt_gatt_server *gatt;
  34. struct bt_gatt_client *client;
  35. };
  36. static int att_fd = -1;
  37. static struct queue *conn_list = NULL;
  38. static struct gatt_db *gatt_db = NULL;
  39. static struct gatt_db *gatt_cache = NULL;
  40. static uint8_t static_addr[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  41. static uint8_t dev_name[20];
  42. static uint8_t dev_name_len = 0;
  43. void gatt_set_static_address(uint8_t addr[6])
  44. {
  45. memcpy(static_addr, addr, sizeof(static_addr));
  46. }
  47. void gatt_set_device_name(uint8_t name[20], uint8_t len)
  48. {
  49. memcpy(dev_name, name, sizeof(dev_name));
  50. dev_name_len = len;
  51. }
  52. static void gatt_conn_destroy(void *data)
  53. {
  54. struct gatt_conn *conn = data;
  55. bt_gatt_client_unref(conn->client);
  56. bt_gatt_server_unref(conn->gatt);
  57. bt_att_unref(conn->att);
  58. free(conn);
  59. }
  60. static void gatt_conn_disconnect(int err, void *user_data)
  61. {
  62. struct gatt_conn *conn = user_data;
  63. printf("Device disconnected: %s\n", strerror(err));
  64. queue_remove(conn_list, conn);
  65. gatt_conn_destroy(conn);
  66. }
  67. static void client_ready_callback(bool success, uint8_t att_ecode,
  68. void *user_data)
  69. {
  70. printf("GATT client discovery complete\n");
  71. }
  72. static void client_service_changed_callback(uint16_t start_handle,
  73. uint16_t end_handle,
  74. void *user_data)
  75. {
  76. printf("GATT client service changed notification\n");
  77. }
  78. static struct gatt_conn *gatt_conn_new(int fd)
  79. {
  80. struct gatt_conn *conn;
  81. uint16_t mtu = 0;
  82. conn = new0(struct gatt_conn, 1);
  83. if (!conn)
  84. return NULL;
  85. conn->att = bt_att_new(fd, false);
  86. if (!conn->att) {
  87. fprintf(stderr, "Failed to initialze ATT transport layer\n");
  88. free(conn);
  89. return NULL;
  90. }
  91. bt_att_set_close_on_unref(conn->att, true);
  92. bt_att_register_disconnect(conn->att, gatt_conn_disconnect, conn, NULL);
  93. bt_att_set_security(conn->att, BT_SECURITY_MEDIUM);
  94. conn->gatt = bt_gatt_server_new(gatt_db, conn->att, mtu, 0);
  95. if (!conn->gatt) {
  96. fprintf(stderr, "Failed to create GATT server\n");
  97. bt_att_unref(conn->att);
  98. free(conn);
  99. return NULL;
  100. }
  101. conn->client = bt_gatt_client_new(gatt_cache, conn->att, mtu, 0);
  102. if (!conn->gatt) {
  103. fprintf(stderr, "Failed to create GATT client\n");
  104. bt_gatt_server_unref(conn->gatt);
  105. bt_att_unref(conn->att);
  106. free(conn);
  107. return NULL;
  108. }
  109. bt_gatt_client_ready_register(conn->client, client_ready_callback,
  110. conn, NULL);
  111. bt_gatt_client_set_service_changed(conn->client,
  112. client_service_changed_callback, conn, NULL);
  113. return conn;
  114. }
  115. static void att_conn_callback(int fd, uint32_t events, void *user_data)
  116. {
  117. struct gatt_conn *conn;
  118. struct sockaddr_l2 addr;
  119. socklen_t addrlen;
  120. int new_fd;
  121. if (events & (EPOLLERR | EPOLLHUP)) {
  122. mainloop_remove_fd(fd);
  123. return;
  124. }
  125. memset(&addr, 0, sizeof(addr));
  126. addrlen = sizeof(addr);
  127. new_fd = accept(att_fd, (struct sockaddr *) &addr, &addrlen);
  128. if (new_fd < 0) {
  129. fprintf(stderr, "Failed to accept new ATT connection: %m\n");
  130. return;
  131. }
  132. conn = gatt_conn_new(new_fd);
  133. if (!conn) {
  134. fprintf(stderr, "Failed to create GATT connection\n");
  135. close(new_fd);
  136. return;
  137. }
  138. if (!queue_push_tail(conn_list, conn)) {
  139. fprintf(stderr, "Failed to add GATT connection\n");
  140. gatt_conn_destroy(conn);
  141. close(new_fd);
  142. }
  143. printf("New device connected\n");
  144. }
  145. static void gap_device_name_read(struct gatt_db_attribute *attrib,
  146. unsigned int id, uint16_t offset,
  147. uint8_t opcode, struct bt_att *att,
  148. void *user_data)
  149. {
  150. uint8_t error;
  151. const uint8_t *value;
  152. size_t len;
  153. if (offset > dev_name_len) {
  154. error = BT_ATT_ERROR_INVALID_OFFSET;
  155. value = NULL;
  156. len = dev_name_len;
  157. } else {
  158. error = 0;
  159. len = dev_name_len - offset;
  160. value = len ? &dev_name[offset] : NULL;
  161. }
  162. gatt_db_attribute_read_result(attrib, id, error, value, len);
  163. }
  164. static void populate_gap_service(struct gatt_db *db)
  165. {
  166. struct gatt_db_attribute *service;
  167. bt_uuid_t uuid;
  168. bt_uuid16_create(&uuid, UUID_GAP);
  169. service = gatt_db_add_service(db, &uuid, true, 6);
  170. bt_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
  171. gatt_db_service_add_characteristic(service, &uuid,
  172. BT_ATT_PERM_READ,
  173. BT_GATT_CHRC_PROP_READ,
  174. gap_device_name_read, NULL, NULL);
  175. gatt_db_service_set_active(service, true);
  176. }
  177. static void populate_devinfo_service(struct gatt_db *db)
  178. {
  179. struct gatt_db_attribute *service;
  180. bt_uuid_t uuid;
  181. bt_uuid16_create(&uuid, 0x180a);
  182. service = gatt_db_add_service(db, &uuid, true, 17);
  183. gatt_db_service_set_active(service, true);
  184. }
  185. void gatt_server_start(void)
  186. {
  187. struct sockaddr_l2 addr;
  188. if (att_fd >= 0)
  189. return;
  190. att_fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET | SOCK_CLOEXEC,
  191. BTPROTO_L2CAP);
  192. if (att_fd < 0) {
  193. fprintf(stderr, "Failed to create ATT server socket: %m\n");
  194. return;
  195. }
  196. memset(&addr, 0, sizeof(addr));
  197. addr.l2_family = AF_BLUETOOTH;
  198. addr.l2_cid = htobs(ATT_CID);
  199. memcpy(&addr.l2_bdaddr, static_addr, 6);
  200. addr.l2_bdaddr_type = BDADDR_LE_RANDOM;
  201. if (bind(att_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  202. fprintf(stderr, "Failed to bind ATT server socket: %m\n");
  203. close(att_fd);
  204. att_fd = -1;
  205. return;
  206. }
  207. if (listen(att_fd, 1) < 0) {
  208. fprintf(stderr, "Failed to listen on ATT server socket: %m\n");
  209. close(att_fd);
  210. att_fd = -1;
  211. return;
  212. }
  213. gatt_db = gatt_db_new();
  214. if (!gatt_db) {
  215. close(att_fd);
  216. att_fd = -1;
  217. return;
  218. }
  219. populate_gap_service(gatt_db);
  220. populate_devinfo_service(gatt_db);
  221. gatt_cache = gatt_db_new();
  222. conn_list = queue_new();
  223. if (!conn_list) {
  224. gatt_db_unref(gatt_db);
  225. gatt_db = NULL;
  226. close(att_fd);
  227. att_fd = -1;
  228. return;
  229. }
  230. mainloop_add_fd(att_fd, EPOLLIN, att_conn_callback, NULL, NULL);
  231. }
  232. void gatt_server_stop(void)
  233. {
  234. if (att_fd < 0)
  235. return;
  236. mainloop_remove_fd(att_fd);
  237. queue_destroy(conn_list, gatt_conn_destroy);
  238. gatt_db_unref(gatt_cache);
  239. gatt_cache = NULL;
  240. gatt_db_unref(gatt_db);
  241. gatt_db = NULL;
  242. close(att_fd);
  243. att_fd = -1;
  244. }