seos_service.c 7.6 KB

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