gatt.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2017 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 <errno.h>
  15. #include <unistd.h>
  16. #include <stdlib.h>
  17. #include <stdbool.h>
  18. #include <sys/uio.h>
  19. #include <wordexp.h>
  20. #include <glib.h>
  21. #include "src/shared/io.h"
  22. #include "src/shared/shell.h"
  23. #include "gdbus/gdbus.h"
  24. #include "lib/bluetooth.h"
  25. #include "lib/uuid.h"
  26. #include "tools/mesh-gatt/node.h"
  27. #include "tools/mesh-gatt/util.h"
  28. #include "tools/mesh-gatt/gatt.h"
  29. #include "tools/mesh-gatt/prov.h"
  30. #include "tools/mesh-gatt/net.h"
  31. #define MESH_PROV_DATA_OUT_UUID_STR "00002adc-0000-1000-8000-00805f9b34fb"
  32. #define MESH_PROXY_DATA_OUT_UUID_STR "00002ade-0000-1000-8000-00805f9b34fb"
  33. static struct io *write_io;
  34. static uint16_t write_mtu;
  35. static struct io *notify_io;
  36. static uint16_t notify_mtu;
  37. struct write_data {
  38. GDBusProxy *proxy;
  39. void *user_data;
  40. struct iovec iov;
  41. GDBusReturnFunction cb;
  42. uint8_t *gatt_data;
  43. uint8_t gatt_len;
  44. };
  45. struct notify_data {
  46. GDBusProxy *proxy;
  47. bool enable;
  48. GDBusReturnFunction cb;
  49. void *user_data;
  50. };
  51. bool mesh_gatt_is_child(GDBusProxy *proxy, GDBusProxy *parent,
  52. const char *name)
  53. {
  54. DBusMessageIter iter;
  55. const char *parent_path;
  56. if (!parent)
  57. return FALSE;
  58. if (g_dbus_proxy_get_property(proxy, name, &iter) == FALSE)
  59. return FALSE;
  60. dbus_message_iter_get_basic(&iter, &parent_path);
  61. if (!strcmp(parent_path, g_dbus_proxy_get_path(parent)))
  62. return TRUE;
  63. else
  64. return FALSE;
  65. }
  66. /* Refactor this once actual MTU is available */
  67. #define GATT_MTU 23
  68. static void write_data_free(void *user_data)
  69. {
  70. struct write_data *data = user_data;
  71. g_free(data->gatt_data);
  72. free(data);
  73. }
  74. uint16_t mesh_gatt_sar(uint8_t **pkt, uint16_t size)
  75. {
  76. const uint8_t *data = *pkt;
  77. uint8_t gatt_hdr = *data++;
  78. uint8_t type = gatt_hdr & GATT_TYPE_MASK;
  79. static uint8_t gatt_size;
  80. static uint8_t gatt_pkt[67];
  81. print_byte_array("GATT-RX:\t", *pkt, size);
  82. if (size < 1) {
  83. gatt_pkt[0] = GATT_TYPE_INVALID;
  84. /* TODO: Disconnect GATT per last paragraph sec 6.6 */
  85. return 0;
  86. }
  87. size--;
  88. switch (gatt_hdr & GATT_SAR_MASK) {
  89. case GATT_SAR_FIRST:
  90. gatt_size = 1;
  91. gatt_pkt[0] = type;
  92. /* TODO: Start Proxy Timeout */
  93. /* fall through */
  94. case GATT_SAR_CONTINUE:
  95. if (gatt_pkt[0] != type ||
  96. gatt_size + size > MAX_GATT_SIZE) {
  97. /* Invalidate packet and return failure */
  98. gatt_pkt[0] = GATT_TYPE_INVALID;
  99. /* TODO: Disconnect GATT per last paragraph sec 6.6 */
  100. return 0;
  101. }
  102. memcpy(gatt_pkt + gatt_size, data, size);
  103. gatt_size += size;
  104. /* We are good to this point, but incomplete */
  105. return 0;
  106. default:
  107. case GATT_SAR_COMPLETE:
  108. gatt_size = 1;
  109. gatt_pkt[0] = type;
  110. /* fall through */
  111. case GATT_SAR_LAST:
  112. if (gatt_pkt[0] != type ||
  113. gatt_size + size > MAX_GATT_SIZE) {
  114. /* Invalidate packet and return failure */
  115. gatt_pkt[0] = GATT_TYPE_INVALID;
  116. /* Disconnect GATT per last paragraph sec 6.6 */
  117. return 0;
  118. }
  119. memcpy(gatt_pkt + gatt_size, data, size);
  120. gatt_size += size;
  121. *pkt = gatt_pkt;
  122. return gatt_size;
  123. }
  124. }
  125. static int sock_send(struct io *io, struct iovec *iov, size_t iovlen)
  126. {
  127. struct msghdr msg;
  128. int ret;
  129. memset(&msg, 0, sizeof(msg));
  130. msg.msg_iov = iov;
  131. msg.msg_iovlen = iovlen;
  132. ret = sendmsg(io_get_fd(io), &msg, MSG_NOSIGNAL);
  133. if (ret < 0) {
  134. ret = -errno;
  135. bt_shell_printf("sendmsg: %s", strerror(-ret));
  136. }
  137. return ret;
  138. }
  139. static bool sock_write(struct io *io, void *user_data)
  140. {
  141. struct write_data *data = user_data;
  142. struct iovec iov[2];
  143. uint8_t sar;
  144. uint8_t max_len;
  145. if (data == NULL)
  146. return true;
  147. max_len = write_mtu ? write_mtu - 3 - 1 : GATT_MTU - 3 - 1;
  148. print_byte_array("GATT-TX:\t", data->gatt_data, data->gatt_len);
  149. sar = data->gatt_data[0];
  150. data->iov.iov_base = data->gatt_data + 1;
  151. data->iov.iov_len--;
  152. sar = data->gatt_data[0] & GATT_TYPE_MASK;
  153. data->gatt_len--;
  154. if (data->gatt_len > max_len) {
  155. sar |= GATT_SAR_FIRST;
  156. data->iov.iov_len = max_len;
  157. }
  158. iov[0].iov_base = &sar;
  159. iov[0].iov_len = sizeof(sar);
  160. while (1) {
  161. int err;
  162. iov[1] = data->iov;
  163. err = sock_send(io, iov, 2);
  164. if (err < 0) {
  165. write_data_free(data);
  166. return false;
  167. }
  168. switch (sar & GATT_SAR_MASK) {
  169. case GATT_SAR_FIRST:
  170. case GATT_SAR_CONTINUE:
  171. data->gatt_len -= max_len;
  172. data->iov.iov_base = data->iov.iov_base + max_len;
  173. sar &= GATT_TYPE_MASK;
  174. if (max_len < data->gatt_len) {
  175. data->iov.iov_len = max_len;
  176. sar |= GATT_SAR_CONTINUE;
  177. } else {
  178. data->iov.iov_len = data->gatt_len;
  179. sar |= GATT_SAR_LAST;
  180. }
  181. break;
  182. default:
  183. if(data->cb)
  184. data->cb(NULL, data->user_data);
  185. write_data_free(data);
  186. return true;
  187. }
  188. }
  189. }
  190. static void write_io_destroy(void)
  191. {
  192. io_destroy(write_io);
  193. write_io = NULL;
  194. write_mtu = 0;
  195. }
  196. static void notify_io_destroy(void)
  197. {
  198. io_destroy(notify_io);
  199. notify_io = NULL;
  200. notify_mtu = 0;
  201. }
  202. static bool sock_hup(struct io *io, void *user_data)
  203. {
  204. bt_shell_printf("%s closed\n", io == notify_io ? "Notify" : "Write");
  205. if (io == notify_io)
  206. notify_io_destroy();
  207. else
  208. write_io_destroy();
  209. return false;
  210. }
  211. static struct io *sock_io_new(int fd)
  212. {
  213. struct io *io;
  214. io = io_new(fd);
  215. io_set_close_on_destroy(io, true);
  216. io_set_disconnect_handler(io, sock_hup, NULL, NULL);
  217. return io;
  218. }
  219. static void acquire_write_reply(DBusMessage *message, void *user_data)
  220. {
  221. struct write_data *data = user_data;
  222. DBusError error;
  223. int fd;
  224. dbus_error_init(&error);
  225. if (dbus_set_error_from_message(&error, message) == TRUE) {
  226. dbus_error_free(&error);
  227. bt_shell_printf("Failed to write\n");
  228. write_data_free(data);
  229. return;
  230. }
  231. if ((dbus_message_get_args(message, NULL, DBUS_TYPE_UNIX_FD, &fd,
  232. DBUS_TYPE_UINT16, &write_mtu,
  233. DBUS_TYPE_INVALID) == false)) {
  234. bt_shell_printf("Invalid AcquireWrite response\n");
  235. return;
  236. }
  237. bt_shell_printf("AcquireWrite success: fd %d MTU %u\n", fd, write_mtu);
  238. write_io = sock_io_new(fd);
  239. sock_write(write_io, data);
  240. }
  241. static void acquire_setup(DBusMessageIter *iter, void *user_data)
  242. {
  243. DBusMessageIter dict;
  244. dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
  245. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  246. DBUS_TYPE_STRING_AS_STRING
  247. DBUS_TYPE_VARIANT_AS_STRING
  248. DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
  249. &dict);
  250. dbus_message_iter_close_container(iter, &dict);
  251. }
  252. bool mesh_gatt_write(GDBusProxy *proxy, uint8_t *buf, uint16_t len,
  253. GDBusReturnFunction cb, void *user_data)
  254. {
  255. struct write_data *data;
  256. if (!buf || !len)
  257. return false;
  258. if (len > 69)
  259. return false;
  260. data = g_new0(struct write_data, 1);
  261. if (!data)
  262. return false;
  263. /* TODO: should keep in queue in case we need to cancel write? */
  264. data->gatt_len = len;
  265. data->gatt_data = g_memdup(buf, len);
  266. data->gatt_data[0] &= GATT_TYPE_MASK;
  267. data->iov.iov_base = data->gatt_data;
  268. data->iov.iov_len = len;
  269. data->proxy = proxy;
  270. data->user_data = user_data;
  271. data->cb = cb;
  272. if (write_io)
  273. return sock_write(write_io, data);
  274. if (g_dbus_proxy_method_call(proxy, "AcquireWrite",
  275. acquire_setup, acquire_write_reply,
  276. data, NULL) == FALSE) {
  277. bt_shell_printf("Failed to AcquireWrite\n");
  278. write_data_free(data);
  279. return false;
  280. }
  281. return true;
  282. }
  283. static void notify_reply(DBusMessage *message, void *user_data)
  284. {
  285. struct notify_data *data = user_data;
  286. DBusError error;
  287. dbus_error_init(&error);
  288. if (dbus_set_error_from_message(&error, message) == TRUE) {
  289. bt_shell_printf("Failed to %s notify: %s\n",
  290. data->enable ? "start" : "stop", error.name);
  291. dbus_error_free(&error);
  292. goto done;
  293. }
  294. bt_shell_printf("Notify %s\n", data->enable ? "started" : "stopped");
  295. done:
  296. if (data->cb)
  297. data->cb(message, data->user_data);
  298. g_free(data);
  299. }
  300. static bool sock_read(struct io *io, bool prov, void *user_data)
  301. {
  302. struct mesh_node *node = user_data;
  303. struct msghdr msg;
  304. struct iovec iov;
  305. uint8_t buf[512];
  306. uint8_t *res;
  307. int fd = io_get_fd(io);
  308. ssize_t len, len_sar;
  309. if (io != notify_io)
  310. return true;
  311. iov.iov_base = buf;
  312. iov.iov_len = sizeof(buf);
  313. memset(&msg, 0, sizeof(msg));
  314. msg.msg_iov = &iov;
  315. msg.msg_iovlen = 1;
  316. while ((len = recvmsg(fd, &msg, MSG_DONTWAIT))) {
  317. if (len < 0) {
  318. if (errno == EAGAIN)
  319. break;
  320. return false;
  321. }
  322. res = buf;
  323. len_sar = mesh_gatt_sar(&res, len);
  324. if (len_sar) {
  325. if (prov)
  326. prov_data_ready(node, res, len_sar);
  327. else
  328. net_data_ready(res, len_sar);
  329. }
  330. }
  331. /* When socket is orderly closed, then recvmsg returns 0 */
  332. if (len == 0)
  333. return false;
  334. return true;
  335. }
  336. static bool sock_read_prov(struct io *io, void *user_data)
  337. {
  338. return sock_read(io, true, user_data);
  339. }
  340. static bool sock_read_proxy(struct io *io, void *user_data)
  341. {
  342. return sock_read(io, false, user_data);
  343. }
  344. static void acquire_notify_reply(DBusMessage *message, void *user_data)
  345. {
  346. struct notify_data *data = user_data;
  347. DBusMessageIter iter;
  348. DBusError error;
  349. int fd;
  350. const char *uuid;
  351. dbus_error_init(&error);
  352. if (dbus_set_error_from_message(&error, message) == TRUE) {
  353. dbus_error_free(&error);
  354. if (g_dbus_proxy_method_call(data->proxy, "StartNotify", NULL,
  355. notify_reply, data, NULL) == FALSE) {
  356. bt_shell_printf("Failed to StartNotify\n");
  357. g_free(data);
  358. }
  359. return;
  360. }
  361. if (notify_io) {
  362. io_destroy(notify_io);
  363. notify_io = NULL;
  364. }
  365. notify_mtu = 0;
  366. if ((dbus_message_get_args(message, NULL, DBUS_TYPE_UNIX_FD, &fd,
  367. DBUS_TYPE_UINT16, &notify_mtu,
  368. DBUS_TYPE_INVALID) == false)) {
  369. if (g_dbus_proxy_method_call(data->proxy, "StartNotify", NULL,
  370. notify_reply, data, NULL) == FALSE) {
  371. bt_shell_printf("Failed to StartNotify\n");
  372. g_free(data);
  373. }
  374. return;
  375. }
  376. bt_shell_printf("AcquireNotify success: fd %d MTU %u\n", fd, notify_mtu);
  377. if (g_dbus_proxy_get_property(data->proxy, "UUID", &iter) == FALSE)
  378. goto done;
  379. notify_io = sock_io_new(fd);
  380. dbus_message_iter_get_basic(&iter, &uuid);
  381. if (!bt_uuid_strcmp(uuid, MESH_PROV_DATA_OUT_UUID_STR))
  382. io_set_read_handler(notify_io, sock_read_prov, data->user_data,
  383. NULL);
  384. else if (!bt_uuid_strcmp(uuid, MESH_PROXY_DATA_OUT_UUID_STR))
  385. io_set_read_handler(notify_io, sock_read_proxy, data->user_data,
  386. NULL);
  387. done:
  388. if (data->cb)
  389. data->cb(message, data->user_data);
  390. g_free(data);
  391. }
  392. bool mesh_gatt_notify(GDBusProxy *proxy, bool enable, GDBusReturnFunction cb,
  393. void *user_data)
  394. {
  395. struct notify_data *data;
  396. DBusMessageIter iter;
  397. const char *method;
  398. GDBusSetupFunction setup = NULL;
  399. data = g_new0(struct notify_data, 1);
  400. data->proxy = proxy;
  401. data->enable = enable;
  402. data->cb = cb;
  403. data->user_data = user_data;
  404. if (enable == TRUE) {
  405. if (g_dbus_proxy_get_property(proxy, "NotifyAcquired", &iter)) {
  406. method = "AcquireNotify";
  407. cb = acquire_notify_reply;
  408. setup = acquire_setup;
  409. } else {
  410. method = "StartNotify";
  411. cb = notify_reply;
  412. }
  413. } else {
  414. if (notify_io) {
  415. notify_io_destroy();
  416. if (cb)
  417. cb(NULL, user_data);
  418. g_free(data);
  419. return true;
  420. } else {
  421. method = "StopNotify";
  422. cb = notify_reply;
  423. }
  424. }
  425. if (g_dbus_proxy_method_call(proxy, method, setup, cb,
  426. data, NULL) == FALSE) {
  427. bt_shell_printf("Failed to %s\n", method);
  428. return false;
  429. }
  430. return true;
  431. }