app_main.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /* main.c - Application main entry point */
  2. /*
  3. * Copyright (c) 2015-2016 Intel Corporation
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. */
  7. #include <errno.h>
  8. #include <stddef.h>
  9. #include <string.h>
  10. #include "base/byteorder.h"
  11. #include "base/types.h"
  12. #include <bluetooth/bluetooth.h>
  13. #include <bluetooth/conn.h>
  14. #include <bluetooth/gatt.h>
  15. #include <bluetooth/hci.h>
  16. #include <bluetooth/uuid.h>
  17. #include <logging/bt_log_impl.h>
  18. static int scan_start(void);
  19. static struct bt_conn *default_conn;
  20. static struct bt_uuid_16 uuid = BT_UUID_INIT_16(0);
  21. static struct bt_gatt_discover_params discover_params;
  22. static struct bt_gatt_subscribe_params subscribe_params;
  23. static double pow_cal(double x, double y)
  24. {
  25. double result = 1;
  26. if (y < 0)
  27. {
  28. y = -y;
  29. while (y--)
  30. {
  31. result /= x;
  32. }
  33. }
  34. else
  35. {
  36. while (y--)
  37. {
  38. result *= x;
  39. }
  40. }
  41. return result;
  42. }
  43. static uint8_t notify_func(struct bt_conn *conn, struct bt_gatt_subscribe_params *params,
  44. const void *data, uint16_t length)
  45. {
  46. double temperature;
  47. uint32_t mantissa;
  48. int8_t exponent;
  49. if (!data)
  50. {
  51. printk("[UNSUBSCRIBED]\n");
  52. params->value_handle = 0U;
  53. return BT_GATT_ITER_STOP;
  54. }
  55. /* temperature value display */
  56. mantissa = sys_get_le24(&((uint8_t *)data)[1]);
  57. exponent = ((uint8_t *)data)[4];
  58. temperature = (double)mantissa * pow_cal(10, exponent);
  59. printf("Temperature %gC.\n", temperature);
  60. return BT_GATT_ITER_CONTINUE;
  61. }
  62. static uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *attr,
  63. struct bt_gatt_discover_params *params)
  64. {
  65. int err;
  66. if (!attr)
  67. {
  68. printk("Discover complete\n");
  69. (void)memset(params, 0, sizeof(*params));
  70. return BT_GATT_ITER_STOP;
  71. }
  72. printk("[ATTRIBUTE] handle %u\n", attr->handle);
  73. if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_HTS))
  74. {
  75. memcpy(&uuid, BT_UUID_HTS_MEASUREMENT, sizeof(uuid));
  76. discover_params.uuid = &uuid.uuid;
  77. discover_params.start_handle = attr->handle + 1;
  78. discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
  79. err = bt_gatt_discover(conn, &discover_params);
  80. if (err)
  81. {
  82. printk("Discover failed (err %d)\n", err);
  83. }
  84. }
  85. else if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_HTS_MEASUREMENT))
  86. {
  87. memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
  88. discover_params.uuid = &uuid.uuid;
  89. discover_params.start_handle = attr->handle + 2;
  90. discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
  91. subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
  92. err = bt_gatt_discover(conn, &discover_params);
  93. if (err)
  94. {
  95. printk("Discover failed (err %d)\n", err);
  96. }
  97. }
  98. else
  99. {
  100. subscribe_params.notify = notify_func;
  101. subscribe_params.value = BT_GATT_CCC_INDICATE;
  102. subscribe_params.ccc_handle = attr->handle;
  103. err = bt_gatt_subscribe(conn, &subscribe_params);
  104. if (err && err != -EALREADY)
  105. {
  106. printk("Subscribe failed (err %d)\n", err);
  107. }
  108. else
  109. {
  110. printk("[SUBSCRIBED]\n");
  111. }
  112. return BT_GATT_ITER_STOP;
  113. }
  114. return BT_GATT_ITER_STOP;
  115. }
  116. static void connected(struct bt_conn *conn, uint8_t conn_err)
  117. {
  118. char addr[BT_ADDR_LE_STR_LEN];
  119. int err;
  120. bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
  121. if (conn_err)
  122. {
  123. printk("Failed to connect to %s (%u)\n", addr, conn_err);
  124. // bt_conn_unref(default_conn);
  125. default_conn = NULL;
  126. scan_start();
  127. return;
  128. }
  129. printk("Connected: %s\n", addr);
  130. if (conn == default_conn)
  131. {
  132. memcpy(&uuid, BT_UUID_HTS, sizeof(uuid));
  133. discover_params.uuid = &uuid.uuid;
  134. discover_params.func = discover_func;
  135. discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
  136. discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
  137. discover_params.type = BT_GATT_DISCOVER_PRIMARY;
  138. err = bt_gatt_discover(default_conn, &discover_params);
  139. if (err)
  140. {
  141. printk("Discover failed(err %d)\n", err);
  142. return;
  143. }
  144. }
  145. }
  146. static bool eir_found(struct bt_data *data, void *user_data)
  147. {
  148. bt_addr_le_t *addr = user_data;
  149. int i;
  150. printk("[AD]: %u data_len %u\n", data->type, data->data_len);
  151. switch (data->type)
  152. {
  153. case BT_DATA_UUID16_SOME:
  154. case BT_DATA_UUID16_ALL:
  155. if (data->data_len % sizeof(uint16_t) != 0U)
  156. {
  157. printk("AD malformed\n");
  158. return true;
  159. }
  160. for (i = 0; i < data->data_len; i += sizeof(uint16_t))
  161. {
  162. struct bt_uuid *tmp_uuid;
  163. uint16_t u16;
  164. int err;
  165. memcpy(&u16, &data->data[i], sizeof(u16));
  166. tmp_uuid = BT_UUID_DECLARE_16(sys_le16_to_cpu(u16));
  167. if (bt_uuid_cmp(tmp_uuid, BT_UUID_HTS))
  168. {
  169. continue;
  170. }
  171. err = bt_le_scan_stop();
  172. if (err)
  173. {
  174. printk("Stop LE scan failed (err %d)\n", err);
  175. continue;
  176. }
  177. err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT,
  178. &default_conn);
  179. if (err)
  180. {
  181. printk("Create connection failed (err %d)\n", err);
  182. scan_start();
  183. }
  184. return false;
  185. }
  186. }
  187. return true;
  188. }
  189. static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
  190. struct net_buf_simple *ad)
  191. {
  192. char dev[BT_ADDR_LE_STR_LEN];
  193. bt_addr_le_to_str(addr, dev, sizeof(dev));
  194. printk("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i\n", dev, type, ad->len, rssi);
  195. /* We're only interested in connectable events */
  196. if (type == BT_HCI_ADV_IND || type == BT_HCI_ADV_DIRECT_IND)
  197. {
  198. bt_data_parse(ad, eir_found, (void *)addr);
  199. }
  200. }
  201. static int scan_start(void)
  202. {
  203. /* Use active scanning and disable duplicate filtering to handle any
  204. * devices that might update their advertising data at runtime.
  205. */
  206. struct bt_le_scan_param scan_param = {
  207. .type = BT_LE_SCAN_TYPE_ACTIVE,
  208. .options = BT_LE_SCAN_OPT_NONE,
  209. .interval = BT_GAP_SCAN_FAST_INTERVAL,
  210. .window = BT_GAP_SCAN_FAST_WINDOW,
  211. };
  212. return bt_le_scan_start(&scan_param, device_found);
  213. }
  214. static void disconnected(struct bt_conn *conn, uint8_t reason)
  215. {
  216. char addr[BT_ADDR_LE_STR_LEN];
  217. int err;
  218. bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
  219. printk("Disconnected: %s (reason 0x%02x)\n", addr, reason);
  220. if (default_conn != conn)
  221. {
  222. return;
  223. }
  224. // bt_conn_unref(default_conn);
  225. default_conn = NULL;
  226. err = scan_start();
  227. if (err)
  228. {
  229. printk("Scanning failed to start (err %d)\n", err);
  230. }
  231. }
  232. static struct bt_conn_cb conn_callbacks = {
  233. .connected = connected,
  234. .disconnected = disconnected,
  235. };
  236. void bt_ready(int err)
  237. {
  238. if (err)
  239. {
  240. printk("Bluetooth init failed (err %d)\n", err);
  241. return;
  242. }
  243. printk("Bluetooth initialized\n");
  244. bt_conn_cb_register(&conn_callbacks);
  245. err = scan_start();
  246. if (err)
  247. {
  248. printk("Scanning failed to start (err %d)\n", err);
  249. return;
  250. }
  251. printk("Scanning successfully started\n");
  252. }
  253. void app_polling_work(void)
  254. {
  255. }