mesh-io-unit.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2021 Intel Corporation. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #include <errno.h>
  14. #include <string.h>
  15. #include <sys/time.h>
  16. #include <sys/socket.h>
  17. #include <sys/un.h>
  18. #include <unistd.h>
  19. #include <stdio.h>
  20. #include <ell/ell.h>
  21. #include "mesh/mesh-defs.h"
  22. #include "mesh/dbus.h"
  23. #include "mesh/mesh-io.h"
  24. #include "mesh/mesh-io-api.h"
  25. #include "mesh/mesh-io-generic.h"
  26. struct mesh_io_private {
  27. struct l_io *sio;
  28. void *user_data;
  29. char *unique_name;
  30. mesh_io_ready_func_t ready_callback;
  31. struct l_timeout *tx_timeout;
  32. struct l_queue *rx_regs;
  33. struct l_queue *tx_pkts;
  34. struct sockaddr_un addr;
  35. int fd;
  36. uint16_t interval;
  37. };
  38. struct pvt_rx_reg {
  39. mesh_io_recv_func_t cb;
  40. void *user_data;
  41. uint8_t len;
  42. uint8_t filter[0];
  43. };
  44. struct process_data {
  45. struct mesh_io_private *pvt;
  46. const uint8_t *data;
  47. uint8_t len;
  48. struct mesh_io_recv_info info;
  49. };
  50. struct tx_pkt {
  51. struct mesh_io_send_info info;
  52. bool delete;
  53. uint8_t len;
  54. uint8_t pkt[30];
  55. };
  56. struct tx_pattern {
  57. const uint8_t *data;
  58. uint8_t len;
  59. };
  60. static uint32_t get_instant(void)
  61. {
  62. struct timeval tm;
  63. uint32_t instant;
  64. gettimeofday(&tm, NULL);
  65. instant = tm.tv_sec * 1000;
  66. instant += tm.tv_usec / 1000;
  67. return instant;
  68. }
  69. static uint32_t instant_remaining_ms(uint32_t instant)
  70. {
  71. instant -= get_instant();
  72. return instant;
  73. }
  74. static void process_rx_callbacks(void *v_reg, void *v_rx)
  75. {
  76. struct pvt_rx_reg *rx_reg = v_reg;
  77. struct process_data *rx = v_rx;
  78. if (!memcmp(rx->data, rx_reg->filter, rx_reg->len))
  79. rx_reg->cb(rx_reg->user_data, &rx->info, rx->data, rx->len);
  80. }
  81. static void process_rx(struct mesh_io_private *pvt, int8_t rssi,
  82. uint32_t instant, const uint8_t *addr,
  83. const uint8_t *data, uint8_t len)
  84. {
  85. struct process_data rx = {
  86. .pvt = pvt,
  87. .data = data,
  88. .len = len,
  89. .info.instant = instant,
  90. .info.addr = addr,
  91. .info.chan = 7,
  92. .info.rssi = rssi,
  93. };
  94. l_queue_foreach(pvt->rx_regs, process_rx_callbacks, &rx);
  95. }
  96. static bool incoming(struct l_io *sio, void *user_data)
  97. {
  98. struct mesh_io_private *pvt = user_data;
  99. uint32_t instant;
  100. uint8_t buf[31];
  101. size_t size;
  102. instant = get_instant();
  103. size = recv(pvt->fd, buf, sizeof(buf), MSG_DONTWAIT);
  104. if (size > 9 && buf[0]) {
  105. process_rx(pvt, -20, instant, NULL, buf + 1, (uint8_t)size);
  106. } else if (size == 1 && !buf[0] && pvt->unique_name) {
  107. /* Return DBUS unique name */
  108. size = strlen(pvt->unique_name);
  109. if (size > sizeof(buf) - 2)
  110. return true;
  111. buf[0] = 0;
  112. memcpy(buf + 1, pvt->unique_name, size + 1);
  113. send(pvt->fd, buf, size + 2, MSG_DONTWAIT);
  114. }
  115. return true;
  116. }
  117. static bool find_by_ad_type(const void *a, const void *b)
  118. {
  119. const struct tx_pkt *tx = a;
  120. uint8_t ad_type = L_PTR_TO_UINT(b);
  121. return !ad_type || ad_type == tx->pkt[0];
  122. }
  123. static bool find_by_pattern(const void *a, const void *b)
  124. {
  125. const struct tx_pkt *tx = a;
  126. const struct tx_pattern *pattern = b;
  127. if (tx->len < pattern->len)
  128. return false;
  129. return (!memcmp(tx->pkt, pattern->data, pattern->len));
  130. }
  131. static void free_socket(struct mesh_io_private *pvt)
  132. {
  133. l_io_destroy(pvt->sio);
  134. close(pvt->fd);
  135. unlink(pvt->addr.sun_path);
  136. }
  137. static void hello_callback(struct l_dbus_message *msg, void *user_data)
  138. {
  139. struct mesh_io_private *pvt = user_data;
  140. pvt->unique_name = l_strdup(l_dbus_message_get_destination(msg));
  141. l_debug("User-Daemon unique name: %s", pvt->unique_name);
  142. }
  143. static void get_name(struct l_timeout *timeout, void *user_data)
  144. {
  145. struct mesh_io_private *pvt = user_data;
  146. struct l_dbus *dbus = dbus_get_bus();
  147. struct l_dbus_message *msg;
  148. l_timeout_remove(timeout);
  149. if (!dbus) {
  150. l_timeout_create_ms(20, get_name, pvt, NULL);
  151. return;
  152. }
  153. /* Retrieve unique name */
  154. msg = l_dbus_message_new_method_call(dbus, "org.freedesktop.DBus",
  155. "/org/freedesktop/DBus",
  156. "org.freedesktop.DBus",
  157. "GetId");
  158. l_dbus_message_set_arguments(msg, "");
  159. l_dbus_send_with_reply(dbus, msg, hello_callback, pvt, NULL);
  160. }
  161. static void unit_up(void *user_data)
  162. {
  163. struct mesh_io_private *pvt = user_data;
  164. l_debug("Started io-unit");
  165. if (pvt->ready_callback)
  166. pvt->ready_callback(pvt->user_data, true);
  167. l_timeout_create_ms(1, get_name, pvt, NULL);
  168. }
  169. static bool unit_init(struct mesh_io *io, void *opt,
  170. mesh_io_ready_func_t cb, void *user_data)
  171. {
  172. struct mesh_io_private *pvt;
  173. char *sk_path;
  174. size_t size;
  175. l_debug("Starting Unit test IO");
  176. if (!io || io->pvt)
  177. return false;
  178. sk_path = (char *) opt;
  179. pvt = l_new(struct mesh_io_private, 1);
  180. pvt->addr.sun_family = AF_LOCAL;
  181. snprintf(pvt->addr.sun_path, sizeof(pvt->addr.sun_path), "%s",
  182. sk_path);
  183. pvt->fd = socket(PF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
  184. if (pvt->fd < 0)
  185. goto fail;
  186. unlink(pvt->addr.sun_path);
  187. size = offsetof(struct sockaddr_un, sun_path) +
  188. strlen(pvt->addr.sun_path);
  189. if (bind(pvt->fd, (struct sockaddr *) &pvt->addr, size) < 0)
  190. goto fail;
  191. /* Setup socket handlers */
  192. pvt->sio = l_io_new(pvt->fd);
  193. if (!l_io_set_read_handler(pvt->sio, incoming, pvt, NULL))
  194. goto fail;
  195. pvt->rx_regs = l_queue_new();
  196. pvt->tx_pkts = l_queue_new();
  197. pvt->ready_callback = cb;
  198. pvt->user_data = user_data;
  199. io->pvt = pvt;
  200. l_idle_oneshot(unit_up, pvt, NULL);
  201. return true;
  202. fail:
  203. l_error("Failed to bind Unit Test socket");
  204. free_socket(pvt);
  205. l_free(pvt);
  206. return false;
  207. }
  208. static bool unit_destroy(struct mesh_io *io)
  209. {
  210. struct mesh_io_private *pvt = io->pvt;
  211. if (!pvt)
  212. return true;
  213. l_free(pvt->unique_name);
  214. l_timeout_remove(pvt->tx_timeout);
  215. l_queue_destroy(pvt->rx_regs, l_free);
  216. l_queue_destroy(pvt->tx_pkts, l_free);
  217. free_socket(pvt);
  218. l_free(pvt);
  219. io->pvt = NULL;
  220. return true;
  221. }
  222. static bool unit_caps(struct mesh_io *io, struct mesh_io_caps *caps)
  223. {
  224. struct mesh_io_private *pvt = io->pvt;
  225. if (!pvt || !caps)
  226. return false;
  227. caps->max_num_filters = 255;
  228. caps->window_accuracy = 50;
  229. return true;
  230. }
  231. static bool simple_match(const void *a, const void *b)
  232. {
  233. return a == b;
  234. }
  235. static void send_pkt(struct mesh_io_private *pvt, struct tx_pkt *tx,
  236. uint16_t interval)
  237. {
  238. send(pvt->fd, tx->pkt, tx->len, MSG_DONTWAIT);
  239. if (tx->delete) {
  240. l_queue_remove_if(pvt->tx_pkts, simple_match, tx);
  241. l_free(tx);
  242. }
  243. }
  244. static void tx_to(struct l_timeout *timeout, void *user_data)
  245. {
  246. struct mesh_io_private *pvt = user_data;
  247. struct tx_pkt *tx;
  248. uint16_t ms;
  249. uint8_t count;
  250. if (!pvt)
  251. return;
  252. tx = l_queue_pop_head(pvt->tx_pkts);
  253. if (!tx) {
  254. l_timeout_remove(timeout);
  255. pvt->tx_timeout = NULL;
  256. return;
  257. }
  258. if (tx->info.type == MESH_IO_TIMING_TYPE_GENERAL) {
  259. ms = tx->info.u.gen.interval;
  260. count = tx->info.u.gen.cnt;
  261. if (count != MESH_IO_TX_COUNT_UNLIMITED)
  262. tx->info.u.gen.cnt--;
  263. } else {
  264. ms = 25;
  265. count = 1;
  266. }
  267. tx->delete = !!(count == 1);
  268. send_pkt(pvt, tx, ms);
  269. if (count == 1) {
  270. /* Recalculate wakeup if we are responding to POLL */
  271. tx = l_queue_peek_head(pvt->tx_pkts);
  272. if (tx && tx->info.type == MESH_IO_TIMING_TYPE_POLL_RSP) {
  273. ms = instant_remaining_ms(tx->info.u.poll_rsp.instant +
  274. tx->info.u.poll_rsp.delay);
  275. }
  276. } else
  277. l_queue_push_tail(pvt->tx_pkts, tx);
  278. if (timeout) {
  279. pvt->tx_timeout = timeout;
  280. l_timeout_modify_ms(timeout, ms);
  281. } else
  282. pvt->tx_timeout = l_timeout_create_ms(ms, tx_to, pvt, NULL);
  283. }
  284. static void tx_worker(void *user_data)
  285. {
  286. struct mesh_io_private *pvt = user_data;
  287. struct tx_pkt *tx;
  288. uint32_t delay;
  289. tx = l_queue_peek_head(pvt->tx_pkts);
  290. if (!tx)
  291. return;
  292. switch (tx->info.type) {
  293. case MESH_IO_TIMING_TYPE_GENERAL:
  294. if (tx->info.u.gen.min_delay == tx->info.u.gen.max_delay)
  295. delay = tx->info.u.gen.min_delay;
  296. else {
  297. l_getrandom(&delay, sizeof(delay));
  298. delay %= tx->info.u.gen.max_delay -
  299. tx->info.u.gen.min_delay;
  300. delay += tx->info.u.gen.min_delay;
  301. }
  302. break;
  303. case MESH_IO_TIMING_TYPE_POLL:
  304. if (tx->info.u.poll.min_delay == tx->info.u.poll.max_delay)
  305. delay = tx->info.u.poll.min_delay;
  306. else {
  307. l_getrandom(&delay, sizeof(delay));
  308. delay %= tx->info.u.poll.max_delay -
  309. tx->info.u.poll.min_delay;
  310. delay += tx->info.u.poll.min_delay;
  311. }
  312. break;
  313. case MESH_IO_TIMING_TYPE_POLL_RSP:
  314. /* Delay until Instant + Delay */
  315. delay = instant_remaining_ms(tx->info.u.poll_rsp.instant +
  316. tx->info.u.poll_rsp.delay);
  317. if (delay > 255)
  318. delay = 0;
  319. break;
  320. default:
  321. return;
  322. }
  323. if (!delay)
  324. tx_to(pvt->tx_timeout, pvt);
  325. else if (pvt->tx_timeout)
  326. l_timeout_modify_ms(pvt->tx_timeout, delay);
  327. else
  328. pvt->tx_timeout = l_timeout_create_ms(delay, tx_to, pvt, NULL);
  329. }
  330. static bool send_tx(struct mesh_io *io, struct mesh_io_send_info *info,
  331. const uint8_t *data, uint16_t len)
  332. {
  333. struct mesh_io_private *pvt = io->pvt;
  334. struct tx_pkt *tx;
  335. bool sending = false;
  336. if (!info || !data || !len || len > sizeof(tx->pkt))
  337. return false;
  338. tx = l_new(struct tx_pkt, 1);
  339. memcpy(&tx->info, info, sizeof(tx->info));
  340. memcpy(&tx->pkt, data, len);
  341. tx->len = len;
  342. if (info->type == MESH_IO_TIMING_TYPE_POLL_RSP)
  343. l_queue_push_head(pvt->tx_pkts, tx);
  344. else {
  345. sending = !l_queue_isempty(pvt->tx_pkts);
  346. l_queue_push_tail(pvt->tx_pkts, tx);
  347. }
  348. if (!sending) {
  349. l_timeout_remove(pvt->tx_timeout);
  350. pvt->tx_timeout = NULL;
  351. l_idle_oneshot(tx_worker, pvt, NULL);
  352. }
  353. return true;
  354. }
  355. static bool tx_cancel(struct mesh_io *io, const uint8_t *data, uint8_t len)
  356. {
  357. struct mesh_io_private *pvt = io->pvt;
  358. struct tx_pkt *tx;
  359. if (!data)
  360. return false;
  361. if (len == 1) {
  362. do {
  363. tx = l_queue_remove_if(pvt->tx_pkts, find_by_ad_type,
  364. L_UINT_TO_PTR(data[0]));
  365. l_free(tx);
  366. } while (tx);
  367. } else {
  368. struct tx_pattern pattern = {
  369. .data = data,
  370. .len = len
  371. };
  372. do {
  373. tx = l_queue_remove_if(pvt->tx_pkts, find_by_pattern,
  374. &pattern);
  375. l_free(tx);
  376. } while (tx);
  377. }
  378. if (l_queue_isempty(pvt->tx_pkts)) {
  379. l_timeout_remove(pvt->tx_timeout);
  380. pvt->tx_timeout = NULL;
  381. }
  382. return true;
  383. }
  384. static bool find_by_filter(const void *a, const void *b)
  385. {
  386. const struct pvt_rx_reg *rx_reg = a;
  387. const uint8_t *filter = b;
  388. return !memcmp(rx_reg->filter, filter, rx_reg->len);
  389. }
  390. static bool recv_register(struct mesh_io *io, const uint8_t *filter,
  391. uint8_t len, mesh_io_recv_func_t cb, void *user_data)
  392. {
  393. struct mesh_io_private *pvt = io->pvt;
  394. struct pvt_rx_reg *rx_reg;
  395. if (!cb || !filter || !len)
  396. return false;
  397. rx_reg = l_queue_remove_if(pvt->rx_regs, find_by_filter, filter);
  398. l_free(rx_reg);
  399. rx_reg = l_malloc(sizeof(*rx_reg) + len);
  400. memcpy(rx_reg->filter, filter, len);
  401. rx_reg->len = len;
  402. rx_reg->cb = cb;
  403. rx_reg->user_data = user_data;
  404. l_queue_push_head(pvt->rx_regs, rx_reg);
  405. return true;
  406. }
  407. static bool recv_deregister(struct mesh_io *io, const uint8_t *filter,
  408. uint8_t len)
  409. {
  410. return true;
  411. }
  412. const struct mesh_io_api mesh_io_unit = {
  413. .init = unit_init,
  414. .destroy = unit_destroy,
  415. .caps = unit_caps,
  416. .send = send_tx,
  417. .reg = recv_register,
  418. .dereg = recv_deregister,
  419. .cancel = tx_cancel,
  420. };