battery.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
  7. * Copyright (C) 2014 Google Inc.
  8. * Copyright (C) 2017 Red Hat Inc.
  9. *
  10. */
  11. #ifdef HAVE_CONFIG_H
  12. #include <config.h>
  13. #endif
  14. #include <ctype.h>
  15. #include <stdbool.h>
  16. #include <stdlib.h>
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. #include <fcntl.h>
  20. #include <errno.h>
  21. #include <glib.h>
  22. #include "lib/bluetooth.h"
  23. #include "lib/hci.h"
  24. #include "lib/sdp.h"
  25. #include "lib/uuid.h"
  26. #include "src/shared/util.h"
  27. #include "src/shared/att.h"
  28. #include "src/shared/queue.h"
  29. #include "src/shared/gatt-db.h"
  30. #include "src/shared/gatt-client.h"
  31. #include "src/plugin.h"
  32. #include "src/adapter.h"
  33. #include "src/device.h"
  34. #include "src/profile.h"
  35. #include "src/service.h"
  36. #include "src/log.h"
  37. #include "src/battery.h"
  38. #include "attrib/att.h"
  39. #define BATTERY_INTERFACE "org.bluez.Battery1"
  40. #define BATT_UUID16 0x180f
  41. /* Generic Attribute/Access Service */
  42. struct batt {
  43. struct btd_battery *battery;
  44. struct btd_device *device;
  45. struct gatt_db *db;
  46. struct bt_gatt_client *client;
  47. struct gatt_db_attribute *attr;
  48. unsigned int batt_level_cb_id;
  49. uint16_t batt_level_io_handle;
  50. uint8_t *initial_value;
  51. uint8_t percentage;
  52. };
  53. static void batt_free(struct batt *batt)
  54. {
  55. gatt_db_unref(batt->db);
  56. bt_gatt_client_unref(batt->client);
  57. btd_device_unref(batt->device);
  58. g_free (batt->initial_value);
  59. if (batt->battery)
  60. btd_battery_unregister(batt->battery);
  61. g_free(batt);
  62. }
  63. static void batt_reset(struct batt *batt)
  64. {
  65. batt->attr = NULL;
  66. batt->percentage = -1;
  67. gatt_db_unref(batt->db);
  68. batt->db = NULL;
  69. bt_gatt_client_unref(batt->client);
  70. batt->client = NULL;
  71. g_free (batt->initial_value);
  72. batt->initial_value = NULL;
  73. if (batt->battery) {
  74. btd_battery_unregister(batt->battery);
  75. batt->battery = NULL;
  76. }
  77. }
  78. static void parse_battery_level(struct batt *batt,
  79. const uint8_t *value)
  80. {
  81. uint8_t percentage;
  82. percentage = value[0];
  83. if (batt->percentage != percentage) {
  84. batt->percentage = percentage;
  85. DBG("Battery Level updated: %d%%", percentage);
  86. if (!batt->battery) {
  87. warn("Trying to update an unregistered battery");
  88. return;
  89. }
  90. btd_battery_update(batt->battery, batt->percentage);
  91. }
  92. }
  93. static void batt_io_value_cb(uint16_t value_handle, const uint8_t *value,
  94. uint16_t length, void *user_data)
  95. {
  96. struct batt *batt = user_data;
  97. if (value_handle == batt->batt_level_io_handle) {
  98. parse_battery_level(batt, value);
  99. } else {
  100. g_assert_not_reached();
  101. }
  102. }
  103. static void batt_io_ccc_written_cb(uint16_t att_ecode, void *user_data)
  104. {
  105. struct batt *batt = user_data;
  106. if (att_ecode != 0) {
  107. error("Battery Level: notifications not enabled %s",
  108. att_ecode2str(att_ecode));
  109. return;
  110. }
  111. batt->battery = btd_battery_register(device_get_path(batt->device),
  112. "GATT Battery Service", NULL);
  113. if (!batt->battery) {
  114. batt_reset(batt);
  115. return;
  116. }
  117. parse_battery_level(batt, batt->initial_value);
  118. g_free (batt->initial_value);
  119. batt->initial_value = NULL;
  120. DBG("Battery Level: notification enabled");
  121. }
  122. static void read_initial_battery_level_cb(bool success,
  123. uint8_t att_ecode,
  124. const uint8_t *value,
  125. uint16_t length,
  126. void *user_data)
  127. {
  128. struct batt *batt = user_data;
  129. if (!success) {
  130. DBG("Reading battery level failed with ATT errror: %u",
  131. att_ecode);
  132. return;
  133. }
  134. if (!length)
  135. return;
  136. batt->initial_value = g_memdup(value, length);
  137. /* request notify */
  138. batt->batt_level_cb_id =
  139. bt_gatt_client_register_notify(batt->client,
  140. batt->batt_level_io_handle,
  141. batt_io_ccc_written_cb,
  142. batt_io_value_cb,
  143. batt,
  144. NULL);
  145. }
  146. static void handle_battery_level(struct batt *batt, uint16_t value_handle)
  147. {
  148. batt->batt_level_io_handle = value_handle;
  149. if (!bt_gatt_client_read_value(batt->client, batt->batt_level_io_handle,
  150. read_initial_battery_level_cb, batt, NULL))
  151. DBG("Failed to send request to read battery level");
  152. }
  153. static bool uuid_cmp(uint16_t u16, const bt_uuid_t *uuid)
  154. {
  155. bt_uuid_t lhs;
  156. bt_uuid16_create(&lhs, u16);
  157. return bt_uuid_cmp(&lhs, uuid) == 0;
  158. }
  159. static void handle_characteristic(struct gatt_db_attribute *attr,
  160. void *user_data)
  161. {
  162. struct batt *batt = user_data;
  163. uint16_t value_handle;
  164. bt_uuid_t uuid;
  165. if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle, NULL,
  166. NULL, &uuid)) {
  167. error("Failed to obtain characteristic data");
  168. return;
  169. }
  170. if (uuid_cmp(GATT_CHARAC_BATTERY_LEVEL, &uuid)) {
  171. handle_battery_level(batt, value_handle);
  172. } else {
  173. char uuid_str[MAX_LEN_UUID_STR];
  174. bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
  175. DBG("Unsupported characteristic: %s", uuid_str);
  176. }
  177. }
  178. static void handle_batt_service(struct batt *batt)
  179. {
  180. gatt_db_service_foreach_char(batt->attr, handle_characteristic, batt);
  181. }
  182. static int batt_probe(struct btd_service *service)
  183. {
  184. struct btd_device *device = btd_service_get_device(service);
  185. struct batt *batt = btd_service_get_user_data(service);
  186. char addr[18];
  187. ba2str(device_get_address(device), addr);
  188. DBG("BATT profile probe (%s)", addr);
  189. /* Ignore, if we were probed for this device already */
  190. if (batt) {
  191. error("Profile probed twice for the same device!");
  192. return -1;
  193. }
  194. batt = g_new0(struct batt, 1);
  195. if (!batt)
  196. return -1;
  197. batt->percentage = -1;
  198. batt->device = btd_device_ref(device);
  199. btd_service_set_user_data(service, batt);
  200. return 0;
  201. }
  202. static void batt_remove(struct btd_service *service)
  203. {
  204. struct btd_device *device = btd_service_get_device(service);
  205. struct batt *batt;
  206. char addr[18];
  207. ba2str(device_get_address(device), addr);
  208. DBG("BATT profile remove (%s)", addr);
  209. batt = btd_service_get_user_data(service);
  210. if (!batt) {
  211. error("BATT service not handled by profile");
  212. return;
  213. }
  214. batt_free(batt);
  215. }
  216. static void foreach_batt_service(struct gatt_db_attribute *attr, void *user_data)
  217. {
  218. struct batt *batt = user_data;
  219. if (batt->attr) {
  220. error("More than one BATT service exists for this device");
  221. return;
  222. }
  223. batt->attr = attr;
  224. handle_batt_service(batt);
  225. }
  226. static int batt_accept(struct btd_service *service)
  227. {
  228. struct btd_device *device = btd_service_get_device(service);
  229. struct gatt_db *db = btd_device_get_gatt_db(device);
  230. struct bt_gatt_client *client = btd_device_get_gatt_client(device);
  231. struct batt *batt = btd_service_get_user_data(service);
  232. char addr[18];
  233. bt_uuid_t batt_uuid;
  234. ba2str(device_get_address(device), addr);
  235. DBG("BATT profile accept (%s)", addr);
  236. if (!batt) {
  237. error("BATT service not handled by profile");
  238. return -1;
  239. }
  240. batt->db = gatt_db_ref(db);
  241. batt->client = bt_gatt_client_clone(client);
  242. /* Handle the BATT services */
  243. bt_uuid16_create(&batt_uuid, BATT_UUID16);
  244. gatt_db_foreach_service(db, &batt_uuid, foreach_batt_service, batt);
  245. if (!batt->attr) {
  246. error("BATT attribute not found");
  247. batt_reset(batt);
  248. return -1;
  249. }
  250. btd_service_connecting_complete(service, 0);
  251. return 0;
  252. }
  253. static int batt_disconnect(struct btd_service *service)
  254. {
  255. struct batt *batt = btd_service_get_user_data(service);
  256. batt_reset(batt);
  257. btd_service_disconnecting_complete(service, 0);
  258. return 0;
  259. }
  260. static struct btd_profile batt_profile = {
  261. .name = "batt-profile",
  262. .remote_uuid = BATTERY_UUID,
  263. .device_probe = batt_probe,
  264. .device_remove = batt_remove,
  265. .accept = batt_accept,
  266. .disconnect = batt_disconnect,
  267. .external = true,
  268. };
  269. static int batt_init(void)
  270. {
  271. return btd_profile_register(&batt_profile);
  272. }
  273. static void batt_exit(void)
  274. {
  275. btd_profile_unregister(&batt_profile);
  276. }
  277. BLUETOOTH_PLUGIN_DEFINE(battery, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
  278. batt_init, batt_exit)