adv_monitor.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2020 Google LLC
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <stdint.h>
  17. #include <stdbool.h>
  18. #include <string.h>
  19. #include "gdbus/gdbus.h"
  20. #include "src/shared/ad.h"
  21. #include "src/shared/util.h"
  22. #include "src/shared/shell.h"
  23. #include "adv_monitor.h"
  24. #define ADV_MONITOR_APP_PATH "/org/bluez/adv_monitor_app"
  25. #define ADV_MONITOR_INTERFACE "org.bluez.AdvertisementMonitor1"
  26. #define RSSI_UNSET_THRESHOLD 127
  27. #define RSSI_UNSET_TIMEOUT 0
  28. #define RSSI_UNSET_SAMPLING_PERIOD 256
  29. struct rssi_setting {
  30. int16_t high_threshold;
  31. uint16_t high_timeout;
  32. int16_t low_threshold;
  33. uint16_t low_timeout;
  34. uint16_t sampling_period;
  35. };
  36. struct pattern {
  37. uint8_t start_pos;
  38. uint8_t ad_data_type;
  39. uint8_t content_len;
  40. uint8_t content[BT_AD_MAX_DATA_LEN];
  41. };
  42. struct adv_monitor {
  43. uint8_t idx;
  44. char *path;
  45. char *type;
  46. struct rssi_setting *rssi;
  47. GSList *patterns;
  48. };
  49. static struct adv_monitor_manager {
  50. GSList *supported_types;
  51. GSList *supported_features;
  52. GDBusProxy *proxy;
  53. gboolean app_registered;
  54. } manager = { NULL, NULL, NULL, FALSE };
  55. static uint8_t adv_mon_idx;
  56. static GSList *adv_mons;
  57. static struct rssi_setting *current_rssi;
  58. static void remove_adv_monitor(void *data, void *user_data);
  59. static DBusMessage *release_adv_monitor(DBusConnection *conn,
  60. DBusMessage *msg, void *user_data)
  61. {
  62. struct adv_monitor *adv_monitor = user_data;
  63. bt_shell_printf("Advertisement monitor %d released\n",
  64. adv_monitor->idx);
  65. remove_adv_monitor(adv_monitor, conn);
  66. return dbus_message_new_method_return(msg);
  67. }
  68. static DBusMessage *activate_adv_monitor(DBusConnection *conn,
  69. DBusMessage *msg, void *user_data)
  70. {
  71. struct adv_monitor *adv_monitor = user_data;
  72. bt_shell_printf("Advertisement monitor %d activated\n",
  73. adv_monitor->idx);
  74. return dbus_message_new_method_return(msg);
  75. }
  76. static DBusMessage *device_found_adv_monitor(DBusConnection *conn,
  77. DBusMessage *msg, void *user_data)
  78. {
  79. struct adv_monitor *adv_monitor = user_data;
  80. const char *device;
  81. dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &device,
  82. DBUS_TYPE_INVALID);
  83. bt_shell_printf("Advertisement monitor %d found device %s\n",
  84. adv_monitor->idx, device);
  85. return dbus_message_new_method_return(msg);
  86. }
  87. static DBusMessage *device_lost_adv_monitor(DBusConnection *conn,
  88. DBusMessage *msg, void *user_data)
  89. {
  90. struct adv_monitor *adv_monitor = user_data;
  91. const char *device;
  92. dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &device,
  93. DBUS_TYPE_INVALID);
  94. bt_shell_printf("Advertisement monitor %d lost device %s\n",
  95. adv_monitor->idx, device);
  96. return dbus_message_new_method_return(msg);
  97. }
  98. static const GDBusMethodTable adv_monitor_methods[] = {
  99. { GDBUS_ASYNC_METHOD("Release", NULL, NULL, release_adv_monitor) },
  100. { GDBUS_ASYNC_METHOD("Activate", NULL, NULL, activate_adv_monitor) },
  101. { GDBUS_ASYNC_METHOD("DeviceFound", GDBUS_ARGS({ "device", "o" }),
  102. NULL, device_found_adv_monitor) },
  103. { GDBUS_ASYNC_METHOD("DeviceLost", GDBUS_ARGS({ "device", "o" }),
  104. NULL, device_lost_adv_monitor) },
  105. { }
  106. };
  107. static gboolean get_type(const GDBusPropertyTable *property,
  108. DBusMessageIter *iter, void *user_data)
  109. {
  110. struct adv_monitor *adv_monitor = user_data;
  111. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
  112. &adv_monitor->type);
  113. return TRUE;
  114. }
  115. static gboolean get_low_threshold(const GDBusPropertyTable *property,
  116. DBusMessageIter *iter, void *user_data)
  117. {
  118. struct adv_monitor *adv_monitor = user_data;
  119. struct rssi_setting *rssi = adv_monitor->rssi;
  120. dbus_message_iter_append_basic(iter, DBUS_TYPE_INT16,
  121. &rssi->low_threshold);
  122. return TRUE;
  123. }
  124. static gboolean get_high_threshold(const GDBusPropertyTable *property,
  125. DBusMessageIter *iter, void *user_data)
  126. {
  127. struct adv_monitor *adv_monitor = user_data;
  128. struct rssi_setting *rssi = adv_monitor->rssi;
  129. dbus_message_iter_append_basic(iter, DBUS_TYPE_INT16,
  130. &rssi->high_threshold);
  131. return TRUE;
  132. }
  133. static gboolean get_low_timeout(const GDBusPropertyTable *property,
  134. DBusMessageIter *iter, void *user_data)
  135. {
  136. struct adv_monitor *adv_monitor = user_data;
  137. struct rssi_setting *rssi = adv_monitor->rssi;
  138. dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
  139. &rssi->low_timeout);
  140. return TRUE;
  141. }
  142. static gboolean get_high_timeout(const GDBusPropertyTable *property,
  143. DBusMessageIter *iter, void *user_data)
  144. {
  145. struct adv_monitor *adv_monitor = user_data;
  146. struct rssi_setting *rssi = adv_monitor->rssi;
  147. dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
  148. &rssi->high_timeout);
  149. return TRUE;
  150. }
  151. static gboolean get_sampling_period(const GDBusPropertyTable *property,
  152. DBusMessageIter *iter, void *user_data)
  153. {
  154. struct adv_monitor *adv_monitor = user_data;
  155. struct rssi_setting *rssi = adv_monitor->rssi;
  156. dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
  157. &rssi->sampling_period);
  158. return TRUE;
  159. }
  160. static gboolean low_threshold_exists(const GDBusPropertyTable *property,
  161. void *data)
  162. {
  163. struct adv_monitor *adv_monitor = data;
  164. return adv_monitor->rssi != NULL &&
  165. adv_monitor->rssi->low_threshold != RSSI_UNSET_THRESHOLD;
  166. }
  167. static gboolean high_threshold_exists(const GDBusPropertyTable *property,
  168. void *data)
  169. {
  170. struct adv_monitor *adv_monitor = data;
  171. return adv_monitor->rssi != NULL &&
  172. adv_monitor->rssi->high_threshold != RSSI_UNSET_THRESHOLD;
  173. }
  174. static gboolean low_timeout_exists(const GDBusPropertyTable *property,
  175. void *data)
  176. {
  177. struct adv_monitor *adv_monitor = data;
  178. return adv_monitor->rssi != NULL &&
  179. adv_monitor->rssi->low_timeout != RSSI_UNSET_TIMEOUT;
  180. }
  181. static gboolean high_timeout_exists(const GDBusPropertyTable *property,
  182. void *data)
  183. {
  184. struct adv_monitor *adv_monitor = data;
  185. return adv_monitor->rssi != NULL &&
  186. adv_monitor->rssi->high_timeout != RSSI_UNSET_TIMEOUT;
  187. }
  188. static gboolean sampling_period_exists(const GDBusPropertyTable *property,
  189. void *data)
  190. {
  191. struct adv_monitor *adv_monitor = data;
  192. return adv_monitor->rssi != NULL &&
  193. adv_monitor->rssi->sampling_period !=
  194. RSSI_UNSET_SAMPLING_PERIOD;
  195. }
  196. static void append_pattern_content_to_dbus(DBusMessageIter *iter,
  197. struct pattern *pattern)
  198. {
  199. DBusMessageIter data_iter;
  200. int idx;
  201. dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
  202. DBUS_TYPE_BYTE_AS_STRING, &data_iter);
  203. for (idx = 0; idx < pattern->content_len; idx++)
  204. dbus_message_iter_append_basic(&data_iter, DBUS_TYPE_BYTE,
  205. &pattern->content[idx]);
  206. dbus_message_iter_close_container(iter, &data_iter);
  207. }
  208. static void append_pattern_to_dbus(void *data, void *user_data)
  209. {
  210. struct pattern *pattern = data;
  211. DBusMessageIter *array_iter = user_data;
  212. DBusMessageIter data_iter;
  213. dbus_message_iter_open_container(array_iter, DBUS_TYPE_STRUCT,
  214. NULL, &data_iter);
  215. dbus_message_iter_append_basic(&data_iter, DBUS_TYPE_BYTE,
  216. &pattern->start_pos);
  217. dbus_message_iter_append_basic(&data_iter, DBUS_TYPE_BYTE,
  218. &pattern->ad_data_type);
  219. append_pattern_content_to_dbus(&data_iter, pattern);
  220. dbus_message_iter_close_container(array_iter, &data_iter);
  221. }
  222. static gboolean get_patterns(const GDBusPropertyTable *property,
  223. DBusMessageIter *iter, void *user_data)
  224. {
  225. struct adv_monitor *adv_monitor = user_data;
  226. DBusMessageIter array_iter;
  227. dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "(yyay)",
  228. &array_iter);
  229. g_slist_foreach(adv_monitor->patterns, append_pattern_to_dbus,
  230. &array_iter);
  231. dbus_message_iter_close_container(iter, &array_iter);
  232. return TRUE;
  233. }
  234. static gboolean pattern_exists(const GDBusPropertyTable *property, void *data)
  235. {
  236. struct adv_monitor *adv_monitor = data;
  237. return adv_monitor->patterns != NULL;
  238. }
  239. static const GDBusPropertyTable adv_monitor_props[] = {
  240. { "Type", "s", get_type },
  241. { "RSSILowThreshold", "n", get_low_threshold, NULL,
  242. low_threshold_exists },
  243. { "RSSIHighThreshold", "n", get_high_threshold, NULL,
  244. high_threshold_exists },
  245. { "RSSILowTimeout", "q", get_low_timeout, NULL, low_timeout_exists },
  246. { "RSSIHighTimeout", "q", get_high_timeout, NULL, high_timeout_exists },
  247. { "RSSISamplingPeriod", "q", get_sampling_period, NULL,
  248. sampling_period_exists },
  249. { "Patterns", "a(yyay)", get_patterns, NULL, pattern_exists },
  250. { }
  251. };
  252. static void set_supported_list(GSList **list, DBusMessageIter *iter)
  253. {
  254. char *str;
  255. DBusMessageIter subiter;
  256. dbus_message_iter_recurse(iter, &subiter);
  257. while (dbus_message_iter_get_arg_type(&subiter) ==
  258. DBUS_TYPE_STRING) {
  259. dbus_message_iter_get_basic(&subiter, &str);
  260. *list = g_slist_append(*list, str);
  261. dbus_message_iter_next(&subiter);
  262. }
  263. }
  264. void adv_monitor_add_manager(DBusConnection *conn, GDBusProxy *proxy)
  265. {
  266. DBusMessageIter iter;
  267. if (manager.proxy != NULL || manager.supported_types != NULL ||
  268. manager.supported_features != NULL) {
  269. bt_shell_printf("advertisement monitor manager already "
  270. "added\n");
  271. return;
  272. }
  273. manager.proxy = proxy;
  274. if (g_dbus_proxy_get_property(proxy, "SupportedMonitorTypes", &iter))
  275. set_supported_list(&(manager.supported_types), &iter);
  276. if (g_dbus_proxy_get_property(proxy, "SupportedFeatures", &iter))
  277. set_supported_list(&(manager.supported_features), &iter);
  278. }
  279. void adv_monitor_remove_manager(DBusConnection *conn)
  280. {
  281. if (manager.supported_types != NULL) {
  282. g_slist_free(manager.supported_types);
  283. manager.supported_types = NULL;
  284. }
  285. if (manager.supported_features != NULL) {
  286. g_slist_free(manager.supported_features);
  287. manager.supported_features = NULL;
  288. }
  289. manager.proxy = NULL;
  290. manager.app_registered = FALSE;
  291. g_free(current_rssi);
  292. current_rssi = NULL;
  293. }
  294. static void register_setup(DBusMessageIter *iter, void *user_data)
  295. {
  296. const char *path = "/";
  297. dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
  298. }
  299. static void register_reply(DBusMessage *message, void *user_data)
  300. {
  301. DBusError error;
  302. dbus_error_init(&error);
  303. if (!dbus_set_error_from_message(&error, message)) {
  304. bt_shell_printf("AdvertisementMonitor path registered\n");
  305. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  306. }
  307. bt_shell_printf("Failed to register path: %s\n", error.name);
  308. dbus_error_free(&error);
  309. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  310. }
  311. static void unregister_setup(DBusMessageIter *iter, void *user_data)
  312. {
  313. const char *path = "/";
  314. dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
  315. }
  316. static void unregister_reply(DBusMessage *message, void *user_data)
  317. {
  318. DBusError error;
  319. dbus_error_init(&error);
  320. if (!dbus_set_error_from_message(&error, message)) {
  321. bt_shell_printf("AdvertisementMonitor path unregistered\n");
  322. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  323. }
  324. bt_shell_printf("Failed to unregister Advertisement Monitor:"
  325. " %s\n", error.name);
  326. dbus_error_free(&error);
  327. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  328. }
  329. void adv_monitor_register_app(DBusConnection *conn)
  330. {
  331. if (manager.app_registered) {
  332. bt_shell_printf("Advertisement Monitor already registered\n");
  333. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  334. } else if (manager.supported_types == NULL ||
  335. !g_dbus_proxy_method_call(manager.proxy, "RegisterMonitor",
  336. register_setup, register_reply,
  337. NULL, NULL)) {
  338. bt_shell_printf("Failed to register Advertisement Monitor\n");
  339. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  340. }
  341. manager.app_registered = TRUE;
  342. }
  343. void adv_monitor_unregister_app(DBusConnection *conn)
  344. {
  345. if (!manager.app_registered) {
  346. bt_shell_printf("Advertisement Monitor not registered\n");
  347. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  348. } else if (!g_dbus_proxy_method_call(manager.proxy, "UnregisterMonitor",
  349. unregister_setup, unregister_reply,
  350. NULL, NULL)) {
  351. bt_shell_printf("Failed to unregister Advertisement Monitor\n");
  352. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  353. }
  354. manager.app_registered = FALSE;
  355. }
  356. static void free_pattern(void *user_data)
  357. {
  358. struct pattern *p = user_data;
  359. g_free(p);
  360. }
  361. static void free_adv_monitor(void *user_data)
  362. {
  363. struct adv_monitor *adv_monitor = user_data;
  364. g_free(adv_monitor->path);
  365. g_free(adv_monitor->type);
  366. g_free(adv_monitor->rssi);
  367. g_slist_free_full(adv_monitor->patterns, free_pattern);
  368. g_free(adv_monitor);
  369. }
  370. static uint8_t str2bytearray(char *str, uint8_t *arr)
  371. {
  372. int idx, len = strlen(str), arr_len = 0;
  373. if (len%2 != 0)
  374. return 0;
  375. for (idx = 0; idx < len; idx += 2) {
  376. if (sscanf(str+idx, "%2hhx", &arr[arr_len++]) < 1)
  377. return 0;
  378. }
  379. return arr_len;
  380. }
  381. static struct pattern *parse_pattern(char *parameter_list[])
  382. {
  383. struct pattern *pat;
  384. pat = g_malloc0(sizeof(struct pattern));
  385. if (!pat) {
  386. bt_shell_printf("Failed to allocate pattern\n");
  387. bt_shell_noninteractive_quit(EXIT_FAILURE);
  388. return NULL;
  389. }
  390. pat->start_pos = atoi(parameter_list[0]);
  391. pat->ad_data_type = atoi(parameter_list[1]);
  392. pat->content_len = str2bytearray(parameter_list[2], pat->content);
  393. if (pat->content_len == 0) {
  394. free_pattern(pat);
  395. return NULL;
  396. }
  397. return pat;
  398. }
  399. static GSList *parse_patterns(char *pattern_list[], int num)
  400. {
  401. GSList *patterns = NULL;
  402. int cnt;
  403. if (num == 0) {
  404. bt_shell_printf("No pattern provided\n");
  405. return NULL;
  406. }
  407. if (num%3) {
  408. bt_shell_printf("Expected %d more arguments\n", 3 - num%3);
  409. return NULL;
  410. }
  411. for (cnt = 0; cnt < num; cnt += 3) {
  412. struct pattern *pattern;
  413. pattern = parse_pattern(pattern_list+cnt);
  414. if (pattern == NULL) {
  415. g_slist_free_full(patterns, free_pattern);
  416. return NULL;
  417. }
  418. patterns = g_slist_append(patterns, pattern);
  419. }
  420. return patterns;
  421. }
  422. static void remove_adv_monitor(void *data, void *user_data)
  423. {
  424. struct adv_monitor *adv_monitor = data;
  425. DBusConnection *conn = user_data;
  426. adv_mons = g_slist_remove(adv_mons, adv_monitor);
  427. g_dbus_unregister_interface(conn, adv_monitor->path,
  428. ADV_MONITOR_INTERFACE);
  429. }
  430. static gint cmp_adv_monitor_with_idx(gconstpointer a, gconstpointer b)
  431. {
  432. const struct adv_monitor *adv_monitor = a;
  433. uint8_t idx = *(uint8_t *)b;
  434. return adv_monitor->idx != idx;
  435. }
  436. static struct adv_monitor *find_adv_monitor_with_idx(uint8_t monitor_idx)
  437. {
  438. GSList *list;
  439. list = g_slist_find_custom(adv_mons, &monitor_idx,
  440. cmp_adv_monitor_with_idx);
  441. if (list)
  442. return (struct adv_monitor *)list->data;
  443. return NULL;
  444. }
  445. static void print_bytearray(char *prefix, uint8_t *arr, uint8_t len)
  446. {
  447. int idx;
  448. bt_shell_printf("%s", prefix);
  449. for (idx = 0; idx < len; idx++)
  450. bt_shell_printf("%02hhx", arr[idx]);
  451. bt_shell_printf("\n");
  452. }
  453. static void print_adv_monitor(struct adv_monitor *adv_monitor)
  454. {
  455. GSList *l;
  456. bt_shell_printf("Advertisement Monitor %d\n", adv_monitor->idx);
  457. bt_shell_printf("\tpath: %s\n", adv_monitor->path);
  458. bt_shell_printf("\ttype: %s\n", adv_monitor->type);
  459. if (adv_monitor->rssi) {
  460. bt_shell_printf("\trssi:\n");
  461. bt_shell_printf("\t\thigh threshold: %hd\n",
  462. adv_monitor->rssi->high_threshold);
  463. bt_shell_printf("\t\thigh threshold timeout: %hu\n",
  464. adv_monitor->rssi->high_timeout);
  465. bt_shell_printf("\t\tlow threshold: %hd\n",
  466. adv_monitor->rssi->low_threshold);
  467. bt_shell_printf("\t\tlow threshold timeout: %hu\n",
  468. adv_monitor->rssi->low_timeout);
  469. bt_shell_printf("\t\tsampling period: %hu\n",
  470. adv_monitor->rssi->sampling_period);
  471. }
  472. if (adv_monitor->patterns) {
  473. int idx = 1;
  474. for (l = adv_monitor->patterns; l; l = g_slist_next(l), idx++) {
  475. struct pattern *pattern = l->data;
  476. bt_shell_printf("\tpattern %d:\n", idx);
  477. bt_shell_printf("\t\tstart position: %hhu\n",
  478. pattern->start_pos);
  479. bt_shell_printf("\t\tAD data type: %hhu\n",
  480. pattern->ad_data_type);
  481. print_bytearray("\t\tcontent: ", pattern->content,
  482. pattern->content_len);
  483. }
  484. }
  485. }
  486. static struct rssi_setting *get_current_rssi(void)
  487. {
  488. if (current_rssi)
  489. return current_rssi;
  490. current_rssi = g_malloc0(sizeof(struct rssi_setting));
  491. if (!current_rssi)
  492. bt_shell_printf("Failed to allocate rssi setting");
  493. current_rssi->low_threshold = RSSI_UNSET_THRESHOLD;
  494. current_rssi->high_threshold = RSSI_UNSET_THRESHOLD;
  495. current_rssi->low_timeout = RSSI_UNSET_TIMEOUT;
  496. current_rssi->high_timeout = RSSI_UNSET_TIMEOUT;
  497. current_rssi->sampling_period = RSSI_UNSET_SAMPLING_PERIOD;
  498. return current_rssi;
  499. }
  500. void adv_monitor_set_rssi_threshold(int16_t low_threshold,
  501. int16_t high_threshold)
  502. {
  503. struct rssi_setting *rssi = get_current_rssi();
  504. if (!rssi)
  505. return;
  506. rssi->low_threshold = low_threshold;
  507. rssi->high_threshold = high_threshold;
  508. }
  509. void adv_monitor_set_rssi_timeout(uint16_t low_timeout, uint16_t high_timeout)
  510. {
  511. struct rssi_setting *rssi = get_current_rssi();
  512. if (!rssi)
  513. return;
  514. rssi->low_timeout = low_timeout;
  515. rssi->high_timeout = high_timeout;
  516. }
  517. void adv_monitor_set_rssi_sampling_period(uint16_t sampling)
  518. {
  519. struct rssi_setting *rssi = get_current_rssi();
  520. if (!rssi)
  521. return;
  522. rssi->sampling_period = sampling;
  523. }
  524. void adv_monitor_add_monitor(DBusConnection *conn, char *type,
  525. int argc, char *argv[])
  526. {
  527. struct adv_monitor *adv_monitor;
  528. GSList *patterns = NULL;
  529. if (g_slist_length(adv_mons) >= UINT8_MAX) {
  530. bt_shell_printf("Number of advertisement monitor exceeds "
  531. "the limit");
  532. return;
  533. }
  534. while (find_adv_monitor_with_idx(adv_mon_idx))
  535. adv_mon_idx += 1;
  536. patterns = parse_patterns(argv+1, argc-1);
  537. if (patterns == NULL) {
  538. bt_shell_printf("pattern-list malformed\n");
  539. return;
  540. }
  541. adv_monitor = g_malloc0(sizeof(struct adv_monitor));
  542. if (!adv_monitor) {
  543. bt_shell_printf("Failed to allocate adv_monitor");
  544. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  545. }
  546. adv_monitor->idx = adv_mon_idx;
  547. adv_monitor->type = g_strdup(type);
  548. adv_monitor->rssi = current_rssi;
  549. adv_monitor->patterns = patterns;
  550. adv_monitor->path = g_strdup_printf("%s/%hhu", ADV_MONITOR_APP_PATH,
  551. adv_mon_idx);
  552. current_rssi = NULL;
  553. if (g_dbus_register_interface(conn, adv_monitor->path,
  554. ADV_MONITOR_INTERFACE,
  555. adv_monitor_methods, NULL,
  556. adv_monitor_props, adv_monitor,
  557. free_adv_monitor) == FALSE) {
  558. bt_shell_printf("Failed to register advertisement monitor\n");
  559. free_adv_monitor(adv_monitor);
  560. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  561. }
  562. adv_mons = g_slist_append(adv_mons, adv_monitor);
  563. bt_shell_printf("Advertisement Monitor %d added\n", adv_monitor->idx);
  564. }
  565. void adv_monitor_print_monitor(DBusConnection *conn, int monitor_idx)
  566. {
  567. struct adv_monitor *adv_monitor;
  568. GSList *l;
  569. if (monitor_idx < 0) {
  570. for (l = adv_mons; l; l = g_slist_next(l)) {
  571. adv_monitor = l->data;
  572. print_adv_monitor(adv_monitor);
  573. }
  574. return;
  575. }
  576. adv_monitor = find_adv_monitor_with_idx(monitor_idx);
  577. if (adv_monitor == NULL) {
  578. bt_shell_printf("Can't find monitor with index %d\n",
  579. monitor_idx);
  580. return;
  581. }
  582. print_adv_monitor(adv_monitor);
  583. }
  584. void adv_monitor_remove_monitor(DBusConnection *conn, int monitor_idx)
  585. {
  586. struct adv_monitor *adv_monitor;
  587. if (monitor_idx < 0) {
  588. g_slist_foreach(adv_mons, remove_adv_monitor, conn);
  589. return;
  590. }
  591. adv_monitor = find_adv_monitor_with_idx(monitor_idx);
  592. if (adv_monitor == NULL) {
  593. bt_shell_printf("Can't find monitor with index %d\n",
  594. monitor_idx);
  595. return;
  596. }
  597. remove_adv_monitor(adv_monitor, conn);
  598. bt_shell_printf("Monitor %d deleted\n", monitor_idx);
  599. }
  600. static void print_supported_list(GSList *list)
  601. {
  602. GSList *iter;
  603. for (iter = list; iter; iter = g_slist_next(iter)) {
  604. char *data = iter->data;
  605. printf(" %s", data);
  606. }
  607. }
  608. void adv_monitor_get_supported_info(void)
  609. {
  610. bt_shell_printf("Supported Features:");
  611. print_supported_list(manager.supported_features);
  612. bt_shell_printf("\n");
  613. bt_shell_printf("Supported Moniter Types:");
  614. print_supported_list(manager.supported_types);
  615. bt_shell_printf("\n");
  616. }