scan.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2012 Nordic Semiconductor Inc.
  7. * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
  8. *
  9. *
  10. */
  11. #ifdef HAVE_CONFIG_H
  12. #include <config.h>
  13. #endif
  14. #include <stdbool.h>
  15. #include <errno.h>
  16. #include "lib/bluetooth.h"
  17. #include "lib/sdp.h"
  18. #include "lib/uuid.h"
  19. #include "src/log.h"
  20. #include "src/plugin.h"
  21. #include "src/adapter.h"
  22. #include "src/device.h"
  23. #include "src/profile.h"
  24. #include "src/service.h"
  25. #include "src/shared/util.h"
  26. #include "src/shared/att.h"
  27. #include "src/shared/queue.h"
  28. #include "src/shared/gatt-db.h"
  29. #include "src/shared/gatt-client.h"
  30. #include "attrib/att.h"
  31. #include "src/btd.h"
  32. #define SCAN_INTERVAL_WIN_UUID 0x2A4F
  33. #define SCAN_REFRESH_UUID 0x2A31
  34. #define SERVER_REQUIRES_REFRESH 0x00
  35. struct scan {
  36. struct btd_device *device;
  37. struct gatt_db *db;
  38. struct bt_gatt_client *client;
  39. struct gatt_db_attribute *attr;
  40. uint16_t iwhandle;
  41. guint refresh_cb_id;
  42. };
  43. static void scan_free(struct scan *scan)
  44. {
  45. bt_gatt_client_unregister_notify(scan->client, scan->refresh_cb_id);
  46. gatt_db_unref(scan->db);
  47. bt_gatt_client_unref(scan->client);
  48. btd_device_unref(scan->device);
  49. g_free(scan);
  50. }
  51. static void write_scan_params(struct scan *scan)
  52. {
  53. uint8_t value[4];
  54. /* Unless scan parameters are configured, use the known kernel default
  55. * parameters
  56. */
  57. put_le16(btd_opts.defaults.le.scan_interval_autoconnect ?
  58. btd_opts.defaults.le.scan_interval_autoconnect :
  59. 0x60, &value[0]);
  60. put_le16(btd_opts.defaults.le.scan_win_autoconnect ?
  61. btd_opts.defaults.le.scan_win_autoconnect :
  62. 0x30, &value[2]);
  63. bt_gatt_client_write_without_response(scan->client, scan->iwhandle,
  64. false, value, sizeof(value));
  65. }
  66. static void refresh_value_cb(uint16_t value_handle, const uint8_t *value,
  67. uint16_t length, void *user_data)
  68. {
  69. struct scan *scan = user_data;
  70. DBG("Server requires refresh: %d", value[3]);
  71. if (value[3] == SERVER_REQUIRES_REFRESH)
  72. write_scan_params(scan);
  73. }
  74. static void refresh_ccc_written_cb(uint16_t att_ecode, void *user_data)
  75. {
  76. if (att_ecode != 0) {
  77. error("Scan Refresh: notifications not enabled %s",
  78. att_ecode2str(att_ecode));
  79. return;
  80. }
  81. DBG("Scan Refresh: notification enabled");
  82. }
  83. static void handle_refresh(struct scan *scan, uint16_t value_handle)
  84. {
  85. DBG("Scan Refresh handle: 0x%04x", value_handle);
  86. scan->refresh_cb_id = bt_gatt_client_register_notify(scan->client,
  87. value_handle, refresh_ccc_written_cb,
  88. refresh_value_cb, scan, NULL);
  89. }
  90. static void handle_iwin(struct scan *scan, uint16_t value_handle)
  91. {
  92. scan->iwhandle = value_handle;
  93. DBG("Scan Interval Window handle: 0x%04x", scan->iwhandle);
  94. write_scan_params(scan);
  95. }
  96. static void handle_characteristic(struct gatt_db_attribute *attr,
  97. void *user_data)
  98. {
  99. struct scan *scan = user_data;
  100. uint16_t value_handle;
  101. bt_uuid_t uuid, scan_interval_wind_uuid, scan_refresh_uuid;
  102. if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle, NULL,
  103. NULL, &uuid)) {
  104. error("Failed to obtain characteristic data");
  105. return;
  106. }
  107. bt_uuid16_create(&scan_interval_wind_uuid, SCAN_INTERVAL_WIN_UUID);
  108. bt_uuid16_create(&scan_refresh_uuid, SCAN_REFRESH_UUID);
  109. if (bt_uuid_cmp(&scan_interval_wind_uuid, &uuid) == 0)
  110. handle_iwin(scan, value_handle);
  111. else if (bt_uuid_cmp(&scan_refresh_uuid, &uuid) == 0)
  112. handle_refresh(scan, value_handle);
  113. else {
  114. char uuid_str[MAX_LEN_UUID_STR];
  115. bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
  116. DBG("Unsupported characteristic: %s", uuid_str);
  117. }
  118. }
  119. static void foreach_scan_param_service(struct gatt_db_attribute *attr,
  120. void *user_data)
  121. {
  122. struct scan *scan = user_data;
  123. if (scan->attr) {
  124. error("More than one scan params service exists for this "
  125. "device");
  126. return;
  127. }
  128. scan->attr = attr;
  129. gatt_db_service_foreach_char(scan->attr, handle_characteristic, scan);
  130. }
  131. static void scan_reset(struct scan *scan)
  132. {
  133. scan->attr = NULL;
  134. gatt_db_unref(scan->db);
  135. scan->db = NULL;
  136. bt_gatt_client_unref(scan->client);
  137. scan->client = NULL;
  138. }
  139. static int scan_param_accept(struct btd_service *service)
  140. {
  141. struct btd_device *device = btd_service_get_device(service);
  142. struct gatt_db *db = btd_device_get_gatt_db(device);
  143. struct bt_gatt_client *client = btd_device_get_gatt_client(device);
  144. bt_uuid_t scan_parameters_uuid;
  145. struct scan *scan = btd_service_get_user_data(service);
  146. char addr[18];
  147. ba2str(device_get_address(device), addr);
  148. DBG("Scan Parameters Client Driver profile accept (%s)", addr);
  149. if (!scan) {
  150. error("Scan Parameters service not handled by profile");
  151. return -1;
  152. }
  153. scan->db = gatt_db_ref(db);
  154. scan->client = bt_gatt_client_clone(client);
  155. bt_string_to_uuid(&scan_parameters_uuid, SCAN_PARAMETERS_UUID);
  156. gatt_db_foreach_service(db, &scan_parameters_uuid,
  157. foreach_scan_param_service, scan);
  158. if (!scan->attr) {
  159. error("Scan Parameters attribute not found");
  160. scan_reset(scan);
  161. return -1;
  162. }
  163. btd_service_connecting_complete(service, 0);
  164. return 0;
  165. }
  166. static int scan_param_disconnect(struct btd_service *service)
  167. {
  168. struct scan *scan = btd_service_get_user_data(service);
  169. scan_reset(scan);
  170. btd_service_disconnecting_complete(service, 0);
  171. return 0;
  172. }
  173. static void scan_param_remove(struct btd_service *service)
  174. {
  175. struct btd_device *device = btd_service_get_device(service);
  176. struct scan *scan;
  177. char addr[18];
  178. ba2str(device_get_address(device), addr);
  179. DBG("GAP profile remove (%s)", addr);
  180. scan = btd_service_get_user_data(service);
  181. if (!scan) {
  182. error("GAP service not handled by profile");
  183. return;
  184. }
  185. scan_free(scan);
  186. }
  187. static int scan_param_probe(struct btd_service *service)
  188. {
  189. struct btd_device *device = btd_service_get_device(service);
  190. struct scan *scan;
  191. char addr[18];
  192. ba2str(device_get_address(device), addr);
  193. DBG("Scan Parameters Client Driver profile probe (%s)", addr);
  194. /* Ignore, if we were probed for this device already */
  195. scan = btd_service_get_user_data(service);
  196. if (scan) {
  197. error("Profile probed twice for the same service!");
  198. return -1;
  199. }
  200. scan = g_new0(struct scan, 1);
  201. if (!scan)
  202. return -1;
  203. scan->device = btd_device_ref(device);
  204. btd_service_set_user_data(service, scan);
  205. return 0;
  206. }
  207. static struct btd_profile scan_profile = {
  208. .name = "Scan Parameters Client Driver",
  209. .remote_uuid = SCAN_PARAMETERS_UUID,
  210. .device_probe = scan_param_probe,
  211. .device_remove = scan_param_remove,
  212. .accept = scan_param_accept,
  213. .disconnect = scan_param_disconnect,
  214. };
  215. static int scan_param_init(void)
  216. {
  217. return btd_profile_register(&scan_profile);
  218. }
  219. static void scan_param_exit(void)
  220. {
  221. btd_profile_unregister(&scan_profile);
  222. }
  223. BLUETOOTH_PLUGIN_DEFINE(scanparam, VERSION,
  224. BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
  225. scan_param_init, scan_param_exit)