seos_service.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. static const BleGattCharacteristicParams ble_svc_seos_chars[SeosSvcGattCharacteristicCount] = {
  17. [SeosSvcGattCharacteristicRxTx] =
  18. {.name = "SEOS",
  19. .data_prop_type =
  20. FlipperGattCharacteristicDataFixed, // FlipperGattCharacteristicDataCallback
  21. .data.fixed.length = BLE_SVC_SEOS_DATA_LEN_MAX,
  22. .uuid.Char_UUID_128 = BLE_SVC_SEOS_CHAR_UUID,
  23. .uuid_type = UUID_TYPE_128,
  24. .char_properties = CHAR_PROP_WRITE_WITHOUT_RESP | CHAR_PROP_NOTIFY,
  25. .security_permissions = ATTR_PERMISSION_NONE,
  26. .gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE,
  27. .is_variable = CHAR_VALUE_LEN_VARIABLE},
  28. };
  29. struct BleServiceSeos {
  30. uint16_t svc_handle;
  31. BleGattCharacteristicInstance chars[SeosSvcGattCharacteristicCount];
  32. FuriMutex* buff_size_mtx;
  33. uint32_t buff_size;
  34. uint16_t bytes_ready_to_receive;
  35. SeosServiceEventCallback callback;
  36. void* context;
  37. GapSvcEventHandler* event_handler;
  38. };
  39. static BleEventAckStatus ble_svc_seos_event_handler(void* event, void* context) {
  40. FURI_LOG_D(TAG, "ble_svc_seos_event_handler");
  41. BleServiceSeos* seos_svc = (BleServiceSeos*)context;
  42. BleEventAckStatus ret = BleEventNotAck;
  43. hci_event_pckt* event_pckt = (hci_event_pckt*)(((hci_uart_pckt*)event)->data);
  44. evt_blecore_aci* blecore_evt = (evt_blecore_aci*)event_pckt->data;
  45. aci_gatt_attribute_modified_event_rp0* attribute_modified;
  46. if(event_pckt->evt == HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE) {
  47. if(blecore_evt->ecode == ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE) {
  48. attribute_modified = (aci_gatt_attribute_modified_event_rp0*)blecore_evt->data;
  49. if(attribute_modified->Attr_Handle ==
  50. seos_svc->chars[SeosSvcGattCharacteristicRxTx].handle + 2) {
  51. // Descriptor handle
  52. ret = BleEventAckFlowEnable;
  53. FURI_LOG_D(TAG, "RX descriptor event");
  54. } else if(
  55. attribute_modified->Attr_Handle ==
  56. seos_svc->chars[SeosSvcGattCharacteristicRxTx].handle + 1) {
  57. FURI_LOG_D(TAG, "Received %d bytes", attribute_modified->Attr_Data_Length);
  58. if(seos_svc->callback) {
  59. furi_check(
  60. furi_mutex_acquire(seos_svc->buff_size_mtx, FuriWaitForever) ==
  61. FuriStatusOk);
  62. if(attribute_modified->Attr_Data_Length > seos_svc->bytes_ready_to_receive) {
  63. FURI_LOG_W(
  64. TAG,
  65. "Received %d, while was ready to receive %d bytes. Can lead to buffer overflow!",
  66. attribute_modified->Attr_Data_Length,
  67. seos_svc->bytes_ready_to_receive);
  68. }
  69. seos_svc->bytes_ready_to_receive -= MIN(
  70. seos_svc->bytes_ready_to_receive, attribute_modified->Attr_Data_Length);
  71. SeosServiceEvent event = {
  72. .event = SeosServiceEventTypeDataReceived,
  73. .data = {
  74. .buffer = attribute_modified->Attr_Data,
  75. .size = attribute_modified->Attr_Data_Length,
  76. }};
  77. uint32_t buff_free_size = seos_svc->callback(event, seos_svc->context);
  78. FURI_LOG_D(TAG, "Available buff size: %ld", buff_free_size);
  79. furi_check(furi_mutex_release(seos_svc->buff_size_mtx) == FuriStatusOk);
  80. }
  81. ret = BleEventAckFlowEnable;
  82. }
  83. } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
  84. FURI_LOG_T(TAG, "Ack received");
  85. if(seos_svc->callback) {
  86. SeosServiceEvent event = {
  87. .event = SeosServiceEventTypeDataSent,
  88. };
  89. seos_svc->callback(event, seos_svc->context);
  90. }
  91. ret = BleEventAckFlowEnable;
  92. }
  93. }
  94. return ret;
  95. }
  96. BleServiceSeos* ble_svc_seos_start(void) {
  97. FURI_LOG_D(TAG, "ble_svc_seos_start");
  98. BleServiceSeos* seos_svc = malloc(sizeof(BleServiceSeos));
  99. seos_svc->event_handler =
  100. ble_event_dispatcher_register_svc_handler(ble_svc_seos_event_handler, seos_svc);
  101. if(!ble_gatt_service_add(
  102. UUID_TYPE_128, &service_uuid, PRIMARY_SERVICE, 12, &seos_svc->svc_handle)) {
  103. free(seos_svc);
  104. return NULL;
  105. }
  106. for(uint8_t i = 0; i < SeosSvcGattCharacteristicCount; i++) {
  107. FURI_LOG_D(TAG, "ble_gatt_characteristic_init %d", i);
  108. ble_gatt_characteristic_init(
  109. seos_svc->svc_handle, &ble_svc_seos_chars[i], &seos_svc->chars[i]);
  110. }
  111. seos_svc->buff_size_mtx = furi_mutex_alloc(FuriMutexTypeNormal);
  112. return seos_svc;
  113. }
  114. void ble_svc_seos_set_callbacks(
  115. BleServiceSeos* seos_svc,
  116. uint16_t buff_size,
  117. SeosServiceEventCallback callback,
  118. void* context) {
  119. furi_check(seos_svc);
  120. FURI_LOG_D(TAG, "ble_svc_seos_set_callbacks");
  121. seos_svc->callback = callback;
  122. seos_svc->context = context;
  123. seos_svc->buff_size = buff_size;
  124. seos_svc->bytes_ready_to_receive = buff_size;
  125. /*
  126. uint32_t buff_size_reversed = REVERSE_BYTES_U32(seos_svc->buff_size);
  127. ble_gatt_characteristic_update(
  128. seos_svc->svc_handle,
  129. &seos_svc->chars[SeosSvcGattCharacteristicFlowCtrl],
  130. &buff_size_reversed);
  131. */
  132. }
  133. void ble_svc_seos_notify_buffer_is_empty(BleServiceSeos* seos_svc) {
  134. furi_check(seos_svc);
  135. furi_check(seos_svc->buff_size_mtx);
  136. furi_check(furi_mutex_acquire(seos_svc->buff_size_mtx, FuriWaitForever) == FuriStatusOk);
  137. if(seos_svc->bytes_ready_to_receive == 0) {
  138. FURI_LOG_D(TAG, "Buffer is empty. Notifying client");
  139. seos_svc->bytes_ready_to_receive = seos_svc->buff_size;
  140. /*
  141. uint32_t buff_size_reversed = REVERSE_BYTES_U32(seos_svc->buff_size);
  142. ble_gatt_characteristic_update(
  143. seos_svc->svc_handle,
  144. &seos_svc->chars[SeosSvcGattCharacteristicFlowCtrl],
  145. &buff_size_reversed);
  146. */
  147. }
  148. furi_check(furi_mutex_release(seos_svc->buff_size_mtx) == FuriStatusOk);
  149. }
  150. void ble_svc_seos_stop(BleServiceSeos* seos_svc) {
  151. furi_check(seos_svc);
  152. ble_event_dispatcher_unregister_svc_handler(seos_svc->event_handler);
  153. for(uint8_t i = 0; i < SeosSvcGattCharacteristicCount; i++) {
  154. ble_gatt_characteristic_delete(seos_svc->svc_handle, &seos_svc->chars[i]);
  155. }
  156. ble_gatt_service_delete(seos_svc->svc_handle);
  157. furi_mutex_free(seos_svc->buff_size_mtx);
  158. free(seos_svc);
  159. }
  160. bool ble_svc_seos_update_tx(BleServiceSeos* seos_svc, uint8_t* data, uint16_t data_len) {
  161. FURI_LOG_D(TAG, "ble_svc_seos_update_tx");
  162. UNUSED(seos_svc);
  163. UNUSED(data);
  164. if(data_len > BLE_SVC_SEOS_DATA_LEN_MAX) {
  165. return false;
  166. }
  167. /*
  168. for(uint16_t remained = data_len; remained > 0;) {
  169. uint8_t value_len = MIN(BLE_SVC_SEOS_CHAR_VALUE_LEN_MAX, remained);
  170. uint16_t value_offset = data_len - remained;
  171. remained -= value_len;
  172. tBleStatus result = aci_gatt_update_char_value_ext(
  173. 0,
  174. seos_svc->svc_handle,
  175. seos_svc->chars[SeosSvcGattCharacteristicTx].handle,
  176. remained ? 0x00 : 0x02,
  177. data_len,
  178. value_offset,
  179. value_len,
  180. data + value_offset);
  181. if(result) {
  182. FURI_LOG_E(TAG, "Failed updating TX characteristic: %d", result);
  183. return false;
  184. }
  185. }
  186. */
  187. return true;
  188. }