seos_service.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #include "seos_service.h"
  2. #include "app_common.h"
  3. //#include <ble/ble.h>
  4. #include <furi_ble/event_dispatcher.h>
  5. #include <furi_ble/gatt.h>
  6. #include "ble_vs_codes.h"
  7. #include "ble_gatt_aci.h"
  8. #include <furi.h>
  9. #include "seos_service_uuid.inc"
  10. #include <stdint.h>
  11. #define TAG "BtSeosSvc"
  12. typedef enum {
  13. SeosSvcGattCharacteristicRxTx = 0,
  14. SeosSvcGattCharacteristicCount,
  15. } SeosSvcGattCharacteristicId;
  16. typedef struct {
  17. const void* data_ptr;
  18. uint16_t data_len;
  19. } SeosSvcDataWrapper;
  20. static bool
  21. ble_svc_seos_data_callback(const void* context, const uint8_t** data, uint16_t* data_len) {
  22. FURI_LOG_D(TAG, "ble_svc_seos_data_callback");
  23. const SeosSvcDataWrapper* report_data = context;
  24. if(data) {
  25. *data = report_data->data_ptr;
  26. *data_len = report_data->data_len;
  27. } else {
  28. *data_len = BLE_SVC_SEOS_DATA_LEN_MAX;
  29. }
  30. return false;
  31. }
  32. static const BleGattCharacteristicParams ble_svc_seos_chars[SeosSvcGattCharacteristicCount] = {
  33. [SeosSvcGattCharacteristicRxTx] =
  34. {.name = "SEOS",
  35. .data_prop_type = FlipperGattCharacteristicDataCallback,
  36. .data.callback.fn = ble_svc_seos_data_callback,
  37. .data.callback.context = NULL,
  38. //.max_length = BLE_SVC_SEOS_DATA_LEN_MAX,
  39. .uuid.Char_UUID_128 = BLE_SVC_SEOS_CHAR_UUID,
  40. .uuid_type = UUID_TYPE_128,
  41. .char_properties = CHAR_PROP_WRITE_WITHOUT_RESP | CHAR_PROP_NOTIFY,
  42. .security_permissions = ATTR_PERMISSION_NONE,
  43. .gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE,
  44. .is_variable = CHAR_VALUE_LEN_VARIABLE},
  45. };
  46. struct BleServiceSeos {
  47. uint16_t svc_handle;
  48. BleGattCharacteristicInstance chars[SeosSvcGattCharacteristicCount];
  49. FuriMutex* buff_size_mtx;
  50. uint32_t buff_size;
  51. uint16_t bytes_ready_to_receive;
  52. SeosServiceEventCallback callback;
  53. void* context;
  54. GapSvcEventHandler* event_handler;
  55. };
  56. static BleEventAckStatus ble_svc_seos_event_handler(void* event, void* context) {
  57. FURI_LOG_D(TAG, "ble_svc_seos_event_handler");
  58. BleServiceSeos* seos_svc = (BleServiceSeos*)context;
  59. BleEventAckStatus ret = BleEventNotAck;
  60. hci_event_pckt* event_pckt = (hci_event_pckt*)(((hci_uart_pckt*)event)->data);
  61. evt_blecore_aci* blecore_evt = (evt_blecore_aci*)event_pckt->data;
  62. aci_gatt_attribute_modified_event_rp0* attribute_modified;
  63. if(event_pckt->evt == HCI_LE_META_EVT_CODE) {
  64. // FURI_LOG_D(TAG, "ble_svc_seos_event_handler HCI_LE_META_EVT_CODE %02x", event_pckt->data[0]);
  65. } else if(event_pckt->evt == HCI_DISCONNECTION_COMPLETE_EVT_CODE) {
  66. } else if(event_pckt->evt == HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE) {
  67. if(blecore_evt->ecode == ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE) {
  68. FURI_LOG_D(TAG, "Process modification events");
  69. attribute_modified = (aci_gatt_attribute_modified_event_rp0*)blecore_evt->data;
  70. if(attribute_modified->Attr_Handle ==
  71. seos_svc->chars[SeosSvcGattCharacteristicRxTx].handle + 2) {
  72. // Descriptor handle
  73. ret = BleEventAckFlowEnable;
  74. if(attribute_modified->Attr_Data_Length == 2) {
  75. uint16_t* value = (uint16_t*)attribute_modified->Attr_Data;
  76. FURI_LOG_D(TAG, "descriptor event %04x", *value);
  77. if(*value == 1) { // ENABLE_NOTIFICATION_VALUE)
  78. uint8_t select[] = {
  79. 0xc0,
  80. 0x00,
  81. 0xa4,
  82. 0x04,
  83. 0x00,
  84. 0x0a,
  85. 0xa0,
  86. 0x00,
  87. 0x00,
  88. 0x04,
  89. 0x40,
  90. 0x00,
  91. 0x01,
  92. 0x01,
  93. 0x00,
  94. 0x01};
  95. SeosSvcDataWrapper report_data = {
  96. .data_ptr = select, .data_len = sizeof(select)};
  97. ble_gatt_characteristic_update(
  98. seos_svc->svc_handle,
  99. &seos_svc->chars[SeosSvcGattCharacteristicRxTx],
  100. &report_data);
  101. }
  102. } else {
  103. FURI_LOG_D(
  104. TAG, "descriptor event %d bytes", attribute_modified->Attr_Data_Length);
  105. }
  106. } else if(
  107. attribute_modified->Attr_Handle ==
  108. seos_svc->chars[SeosSvcGattCharacteristicRxTx].handle + 1) {
  109. FURI_LOG_D(TAG, "Received %d bytes", attribute_modified->Attr_Data_Length);
  110. if(seos_svc->callback) {
  111. furi_check(
  112. furi_mutex_acquire(seos_svc->buff_size_mtx, FuriWaitForever) ==
  113. FuriStatusOk);
  114. if(attribute_modified->Attr_Data_Length > seos_svc->bytes_ready_to_receive) {
  115. FURI_LOG_W(
  116. TAG,
  117. "Received %d, while was ready to receive %d bytes. Can lead to buffer overflow!",
  118. attribute_modified->Attr_Data_Length,
  119. seos_svc->bytes_ready_to_receive);
  120. }
  121. seos_svc->bytes_ready_to_receive -= MIN(
  122. seos_svc->bytes_ready_to_receive, attribute_modified->Attr_Data_Length);
  123. SeosServiceEvent event = {
  124. .event = SeosServiceEventTypeDataReceived,
  125. .data = {
  126. .buffer = attribute_modified->Attr_Data,
  127. .size = attribute_modified->Attr_Data_Length,
  128. }};
  129. uint32_t buff_free_size = seos_svc->callback(event, seos_svc->context);
  130. FURI_LOG_D(TAG, "Available buff size: %ld", buff_free_size);
  131. furi_check(furi_mutex_release(seos_svc->buff_size_mtx) == FuriStatusOk);
  132. } else {
  133. FURI_LOG_W(TAG, "No seos_cvs->callback defined");
  134. }
  135. ret = BleEventAckFlowEnable;
  136. }
  137. } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
  138. FURI_LOG_T(TAG, "Ack received");
  139. if(seos_svc->callback) {
  140. SeosServiceEvent event = {
  141. .event = SeosServiceEventTypeDataSent,
  142. };
  143. seos_svc->callback(event, seos_svc->context);
  144. }
  145. ret = BleEventAckFlowEnable;
  146. } else {
  147. FURI_LOG_D(
  148. TAG,
  149. "ble_svc_seos_event_handler unhandled blecore_evt->ecode %d",
  150. blecore_evt->ecode);
  151. }
  152. } else {
  153. FURI_LOG_D(
  154. TAG, "ble_svc_seos_event_handler unhandled event_pckt->evt %d", event_pckt->evt);
  155. }
  156. return ret;
  157. }
  158. BleServiceSeos* ble_svc_seos_start(void) {
  159. FURI_LOG_D(TAG, "ble_svc_seos_start");
  160. BleServiceSeos* seos_svc = malloc(sizeof(BleServiceSeos));
  161. seos_svc->event_handler =
  162. ble_event_dispatcher_register_svc_handler(ble_svc_seos_event_handler, seos_svc);
  163. if(!ble_gatt_service_add(
  164. UUID_TYPE_128, &service_uuid, PRIMARY_SERVICE, 12, &seos_svc->svc_handle)) {
  165. free(seos_svc);
  166. return NULL;
  167. }
  168. for(uint8_t i = 0; i < SeosSvcGattCharacteristicCount; i++) {
  169. FURI_LOG_D(TAG, "ble_gatt_characteristic_init %d", i);
  170. ble_gatt_characteristic_init(
  171. seos_svc->svc_handle, &ble_svc_seos_chars[i], &seos_svc->chars[i]);
  172. }
  173. seos_svc->buff_size_mtx = furi_mutex_alloc(FuriMutexTypeNormal);
  174. return seos_svc;
  175. }
  176. void ble_svc_seos_set_callbacks(
  177. BleServiceSeos* seos_svc,
  178. uint16_t buff_size,
  179. SeosServiceEventCallback callback,
  180. void* context) {
  181. furi_check(seos_svc);
  182. FURI_LOG_D(TAG, "ble_svc_seos_set_callbacks");
  183. seos_svc->callback = callback;
  184. seos_svc->context = context;
  185. seos_svc->buff_size = buff_size;
  186. seos_svc->bytes_ready_to_receive = buff_size;
  187. }
  188. void ble_svc_seos_notify_buffer_is_empty(BleServiceSeos* seos_svc) {
  189. furi_check(seos_svc);
  190. furi_check(seos_svc->buff_size_mtx);
  191. FURI_LOG_D(TAG, "ble_svc_seos_notify_buffer_is_empty");
  192. furi_check(furi_mutex_acquire(seos_svc->buff_size_mtx, FuriWaitForever) == FuriStatusOk);
  193. if(seos_svc->bytes_ready_to_receive == 0) {
  194. FURI_LOG_D(TAG, "Buffer is empty. Notifying client");
  195. seos_svc->bytes_ready_to_receive = seos_svc->buff_size;
  196. /*
  197. uint32_t buff_size_reversed = REVERSE_BYTES_U32(seos_svc->buff_size);
  198. ble_gatt_characteristic_update(
  199. seos_svc->svc_handle,
  200. &seos_svc->chars[SeosSvcGattCharacteristicFlowCtrl],
  201. &buff_size_reversed);
  202. */
  203. }
  204. furi_check(furi_mutex_release(seos_svc->buff_size_mtx) == FuriStatusOk);
  205. }
  206. void ble_svc_seos_stop(BleServiceSeos* seos_svc) {
  207. furi_check(seos_svc);
  208. ble_event_dispatcher_unregister_svc_handler(seos_svc->event_handler);
  209. for(uint8_t i = 0; i < SeosSvcGattCharacteristicCount; i++) {
  210. ble_gatt_characteristic_delete(seos_svc->svc_handle, &seos_svc->chars[i]);
  211. }
  212. ble_gatt_service_delete(seos_svc->svc_handle);
  213. furi_mutex_free(seos_svc->buff_size_mtx);
  214. free(seos_svc);
  215. }
  216. bool ble_svc_seos_update_tx(BleServiceSeos* seos_svc, uint8_t* data, uint16_t data_len) {
  217. FURI_LOG_D(TAG, "ble_svc_seos_update_tx");
  218. UNUSED(seos_svc);
  219. UNUSED(data);
  220. if(data_len > BLE_SVC_SEOS_DATA_LEN_MAX) {
  221. return false;
  222. }
  223. for(uint16_t remained = data_len; remained > 0;) {
  224. uint8_t value_len = MIN(BLE_SVC_SEOS_CHAR_VALUE_LEN_MAX, remained);
  225. uint16_t value_offset = data_len - remained;
  226. remained -= value_len;
  227. tBleStatus result = aci_gatt_update_char_value_ext(
  228. 0,
  229. seos_svc->svc_handle,
  230. seos_svc->chars[SeosSvcGattCharacteristicRxTx].handle,
  231. remained ? 0x00 : 0x02,
  232. data_len,
  233. value_offset,
  234. value_len,
  235. data + value_offset);
  236. if(result) {
  237. FURI_LOG_E(TAG, "Failed updating TX characteristic: %d", result);
  238. return false;
  239. }
  240. }
  241. return true;
  242. }