dev_info_service.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #include "dev_info_service.h"
  2. #include "app_common.h"
  3. #include <ble/ble.h>
  4. #include <furi.h>
  5. #include <protobuf_version.h>
  6. #include <lib/toolbox/version.h>
  7. #define TAG "BtDevInfoSvc"
  8. typedef struct {
  9. uint16_t service_handle;
  10. uint16_t man_name_char_handle;
  11. uint16_t serial_num_char_handle;
  12. uint16_t firmware_rev_char_handle;
  13. uint16_t software_rev_char_handle;
  14. uint16_t rpc_version_char_handle;
  15. FuriString* version_string;
  16. char hardware_revision[4];
  17. } DevInfoSvc;
  18. static DevInfoSvc* dev_info_svc = NULL;
  19. static const char dev_info_man_name[] = "Flipper Devices Inc.";
  20. static const char dev_info_serial_num[] = "1.0";
  21. static const char dev_info_rpc_version[] = TOSTRING(PROTOBUF_MAJOR_VERSION.PROTOBUF_MINOR_VERSION);
  22. static const uint8_t dev_info_rpc_version_uuid[] =
  23. {0x33, 0xa9, 0xb5, 0x3e, 0x87, 0x5d, 0x1a, 0x8e, 0xc8, 0x47, 0x5e, 0xae, 0x6d, 0x66, 0xf6, 0x03};
  24. void dev_info_svc_start() {
  25. dev_info_svc = malloc(sizeof(DevInfoSvc));
  26. dev_info_svc->version_string = furi_string_alloc_printf(
  27. "%s %s %s %s",
  28. version_get_githash(NULL),
  29. version_get_gitbranch(NULL),
  30. version_get_gitbranchnum(NULL),
  31. version_get_builddate(NULL));
  32. snprintf(
  33. dev_info_svc->hardware_revision,
  34. sizeof(dev_info_svc->hardware_revision),
  35. "%d",
  36. version_get_target(NULL));
  37. tBleStatus status;
  38. // Add Device Information Service
  39. uint16_t uuid = DEVICE_INFORMATION_SERVICE_UUID;
  40. status = aci_gatt_add_service(
  41. UUID_TYPE_16, (Service_UUID_t*)&uuid, PRIMARY_SERVICE, 11, &dev_info_svc->service_handle);
  42. if(status) {
  43. FURI_LOG_E(TAG, "Failed to add Device Information Service: %d", status);
  44. }
  45. // Add characteristics
  46. uuid = MANUFACTURER_NAME_UUID;
  47. status = aci_gatt_add_char(
  48. dev_info_svc->service_handle,
  49. UUID_TYPE_16,
  50. (Char_UUID_t*)&uuid,
  51. strlen(dev_info_man_name),
  52. CHAR_PROP_READ,
  53. ATTR_PERMISSION_AUTHEN_READ,
  54. GATT_DONT_NOTIFY_EVENTS,
  55. 10,
  56. CHAR_VALUE_LEN_CONSTANT,
  57. &dev_info_svc->man_name_char_handle);
  58. if(status) {
  59. FURI_LOG_E(TAG, "Failed to add manufacturer name char: %d", status);
  60. }
  61. uuid = SERIAL_NUMBER_UUID;
  62. status = aci_gatt_add_char(
  63. dev_info_svc->service_handle,
  64. UUID_TYPE_16,
  65. (Char_UUID_t*)&uuid,
  66. strlen(dev_info_serial_num),
  67. CHAR_PROP_READ,
  68. ATTR_PERMISSION_AUTHEN_READ,
  69. GATT_DONT_NOTIFY_EVENTS,
  70. 10,
  71. CHAR_VALUE_LEN_CONSTANT,
  72. &dev_info_svc->serial_num_char_handle);
  73. if(status) {
  74. FURI_LOG_E(TAG, "Failed to add serial number char: %d", status);
  75. }
  76. uuid = FIRMWARE_REVISION_UUID;
  77. status = aci_gatt_add_char(
  78. dev_info_svc->service_handle,
  79. UUID_TYPE_16,
  80. (Char_UUID_t*)&uuid,
  81. strlen(dev_info_svc->hardware_revision),
  82. CHAR_PROP_READ,
  83. ATTR_PERMISSION_AUTHEN_READ,
  84. GATT_DONT_NOTIFY_EVENTS,
  85. 10,
  86. CHAR_VALUE_LEN_CONSTANT,
  87. &dev_info_svc->firmware_rev_char_handle);
  88. if(status) {
  89. FURI_LOG_E(TAG, "Failed to add firmware revision char: %d", status);
  90. }
  91. uuid = SOFTWARE_REVISION_UUID;
  92. status = aci_gatt_add_char(
  93. dev_info_svc->service_handle,
  94. UUID_TYPE_16,
  95. (Char_UUID_t*)&uuid,
  96. furi_string_size(dev_info_svc->version_string),
  97. CHAR_PROP_READ,
  98. ATTR_PERMISSION_AUTHEN_READ,
  99. GATT_DONT_NOTIFY_EVENTS,
  100. 10,
  101. CHAR_VALUE_LEN_CONSTANT,
  102. &dev_info_svc->software_rev_char_handle);
  103. if(status) {
  104. FURI_LOG_E(TAG, "Failed to add software revision char: %d", status);
  105. }
  106. status = aci_gatt_add_char(
  107. dev_info_svc->service_handle,
  108. UUID_TYPE_128,
  109. (const Char_UUID_t*)dev_info_rpc_version_uuid,
  110. strlen(dev_info_rpc_version),
  111. CHAR_PROP_READ,
  112. ATTR_PERMISSION_AUTHEN_READ,
  113. GATT_DONT_NOTIFY_EVENTS,
  114. 10,
  115. CHAR_VALUE_LEN_CONSTANT,
  116. &dev_info_svc->rpc_version_char_handle);
  117. if(status) {
  118. FURI_LOG_E(TAG, "Failed to add rpc version characteristic: %d", status);
  119. }
  120. // Update characteristics
  121. status = aci_gatt_update_char_value(
  122. dev_info_svc->service_handle,
  123. dev_info_svc->man_name_char_handle,
  124. 0,
  125. strlen(dev_info_man_name),
  126. (uint8_t*)dev_info_man_name);
  127. if(status) {
  128. FURI_LOG_E(TAG, "Failed to update manufacturer name char: %d", status);
  129. }
  130. status = aci_gatt_update_char_value(
  131. dev_info_svc->service_handle,
  132. dev_info_svc->serial_num_char_handle,
  133. 0,
  134. strlen(dev_info_serial_num),
  135. (uint8_t*)dev_info_serial_num);
  136. if(status) {
  137. FURI_LOG_E(TAG, "Failed to update serial number char: %d", status);
  138. }
  139. status = aci_gatt_update_char_value(
  140. dev_info_svc->service_handle,
  141. dev_info_svc->firmware_rev_char_handle,
  142. 0,
  143. strlen(dev_info_svc->hardware_revision),
  144. (uint8_t*)dev_info_svc->hardware_revision);
  145. if(status) {
  146. FURI_LOG_E(TAG, "Failed to update firmware revision char: %d", status);
  147. }
  148. status = aci_gatt_update_char_value(
  149. dev_info_svc->service_handle,
  150. dev_info_svc->software_rev_char_handle,
  151. 0,
  152. furi_string_size(dev_info_svc->version_string),
  153. (uint8_t*)furi_string_get_cstr(dev_info_svc->version_string));
  154. if(status) {
  155. FURI_LOG_E(TAG, "Failed to update software revision char: %d", status);
  156. }
  157. status = aci_gatt_update_char_value(
  158. dev_info_svc->service_handle,
  159. dev_info_svc->rpc_version_char_handle,
  160. 0,
  161. strlen(dev_info_rpc_version),
  162. (uint8_t*)dev_info_rpc_version);
  163. if(status) {
  164. FURI_LOG_E(TAG, "Failed to update rpc version char: %d", status);
  165. }
  166. }
  167. void dev_info_svc_stop() {
  168. tBleStatus status;
  169. if(dev_info_svc) {
  170. furi_string_free(dev_info_svc->version_string);
  171. // Delete service characteristics
  172. status =
  173. aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->man_name_char_handle);
  174. if(status) {
  175. FURI_LOG_E(TAG, "Failed to delete manufacturer name char: %d", status);
  176. }
  177. status =
  178. aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->serial_num_char_handle);
  179. if(status) {
  180. FURI_LOG_E(TAG, "Failed to delete serial number char: %d", status);
  181. }
  182. status = aci_gatt_del_char(
  183. dev_info_svc->service_handle, dev_info_svc->firmware_rev_char_handle);
  184. if(status) {
  185. FURI_LOG_E(TAG, "Failed to delete firmware revision char: %d", status);
  186. }
  187. status = aci_gatt_del_char(
  188. dev_info_svc->service_handle, dev_info_svc->software_rev_char_handle);
  189. if(status) {
  190. FURI_LOG_E(TAG, "Failed to delete software revision char: %d", status);
  191. }
  192. status =
  193. aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->rpc_version_char_handle);
  194. if(status) {
  195. FURI_LOG_E(TAG, "Failed to delete rpc version char: %d", status);
  196. }
  197. // Delete service
  198. status = aci_gatt_del_service(dev_info_svc->service_handle);
  199. if(status) {
  200. FURI_LOG_E(TAG, "Failed to delete device info service: %d", status);
  201. }
  202. free(dev_info_svc);
  203. dev_info_svc = NULL;
  204. }
  205. }
  206. bool dev_info_svc_is_started() {
  207. return dev_info_svc != NULL;
  208. }