seos_service.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. #include "seos_service.h"
  2. #include "app_common.h"
  3. #include <furi_ble/event_dispatcher.h>
  4. #include <furi_ble/gatt.h>
  5. #include "ble_vs_codes.h"
  6. #include "ble_gatt_aci.h"
  7. #include <furi.h>
  8. #include "seos_service_uuid.inc"
  9. #include <stdint.h>
  10. #define TAG "BtSeosSvc"
  11. typedef enum {
  12. SeosSvcGattCharacteristicRxTx = 0,
  13. SeosSvcGattCharacteristicCount,
  14. } SeosSvcGattCharacteristicId;
  15. typedef struct {
  16. const void* data_ptr;
  17. uint16_t data_len;
  18. } SeosSvcDataWrapper;
  19. static bool
  20. ble_svc_seos_data_callback(const void* context, const uint8_t** data, uint16_t* data_len) {
  21. const SeosSvcDataWrapper* report_data = context;
  22. if(data) {
  23. *data = report_data->data_ptr;
  24. *data_len = report_data->data_len;
  25. } else {
  26. *data_len = BLE_SVC_SEOS_DATA_LEN_MAX;
  27. }
  28. return false;
  29. }
  30. static const BleGattCharacteristicParams ble_svc_seos_chars[SeosSvcGattCharacteristicCount] = {
  31. [SeosSvcGattCharacteristicRxTx] =
  32. {.name = "SEOS",
  33. .data_prop_type = FlipperGattCharacteristicDataCallback,
  34. .data.callback.fn = ble_svc_seos_data_callback,
  35. .data.callback.context = NULL,
  36. //.max_length = BLE_SVC_SEOS_DATA_LEN_MAX,
  37. .uuid.Char_UUID_128 = BLE_SVC_SEOS_CHAR_UUID,
  38. .uuid_type = UUID_TYPE_128,
  39. .char_properties = CHAR_PROP_WRITE_WITHOUT_RESP | CHAR_PROP_NOTIFY,
  40. .security_permissions = ATTR_PERMISSION_NONE,
  41. .gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE,
  42. .is_variable = CHAR_VALUE_LEN_VARIABLE},
  43. };
  44. struct BleServiceSeos {
  45. uint16_t svc_handle;
  46. BleGattCharacteristicInstance chars[SeosSvcGattCharacteristicCount];
  47. FuriMutex* buff_size_mtx;
  48. uint32_t buff_size;
  49. uint16_t bytes_ready_to_receive;
  50. SeosServiceEventCallback callback;
  51. void* context;
  52. GapSvcEventHandler* event_handler;
  53. };
  54. static BleEventAckStatus ble_svc_seos_event_handler(void* event, void* context) {
  55. BleServiceSeos* seos_svc = (BleServiceSeos*)context;
  56. BleEventAckStatus ret = BleEventNotAck;
  57. hci_event_pckt* event_pckt = (hci_event_pckt*)(((hci_uart_pckt*)event)->data);
  58. evt_blecore_aci* blecore_evt = (evt_blecore_aci*)event_pckt->data;
  59. aci_gatt_attribute_modified_event_rp0* attribute_modified;
  60. if(event_pckt->evt == HCI_LE_META_EVT_CODE) {
  61. } else if(event_pckt->evt == HCI_DISCONNECTION_COMPLETE_EVT_CODE) {
  62. } else if(event_pckt->evt == HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE) {
  63. if(blecore_evt->ecode == ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE) {
  64. attribute_modified = (aci_gatt_attribute_modified_event_rp0*)blecore_evt->data;
  65. if(attribute_modified->Attr_Handle ==
  66. seos_svc->chars[SeosSvcGattCharacteristicRxTx].handle + 2) {
  67. // Descriptor handle
  68. ret = BleEventAckFlowEnable;
  69. if(attribute_modified->Attr_Data_Length == 2) {
  70. uint16_t* value = (uint16_t*)attribute_modified->Attr_Data;
  71. if(*value == 1) { // ENABLE_NOTIFICATION_VALUE)
  72. uint8_t select[] = {
  73. 0xc0,
  74. 0x00,
  75. 0xa4,
  76. 0x04,
  77. 0x00,
  78. 0x0a,
  79. 0xa0,
  80. 0x00,
  81. 0x00,
  82. 0x04,
  83. 0x40,
  84. 0x00,
  85. 0x01,
  86. 0x01,
  87. 0x00,
  88. 0x01};
  89. SeosSvcDataWrapper report_data = {
  90. .data_ptr = select, .data_len = sizeof(select)};
  91. ble_gatt_characteristic_update(
  92. seos_svc->svc_handle,
  93. &seos_svc->chars[SeosSvcGattCharacteristicRxTx],
  94. &report_data);
  95. }
  96. } else {
  97. FURI_LOG_D(
  98. TAG, "descriptor event %d bytes", attribute_modified->Attr_Data_Length);
  99. }
  100. } else if(
  101. attribute_modified->Attr_Handle ==
  102. seos_svc->chars[SeosSvcGattCharacteristicRxTx].handle + 1) {
  103. FURI_LOG_D(TAG, "Received %d bytes", attribute_modified->Attr_Data_Length);
  104. if(seos_svc->callback) {
  105. furi_check(
  106. furi_mutex_acquire(seos_svc->buff_size_mtx, FuriWaitForever) ==
  107. FuriStatusOk);
  108. SeosServiceEvent event = {
  109. .event = SeosServiceEventTypeDataReceived,
  110. .data = {
  111. .buffer = attribute_modified->Attr_Data,
  112. .size = attribute_modified->Attr_Data_Length,
  113. }};
  114. uint32_t buff_free_size = seos_svc->callback(event, seos_svc->context);
  115. FURI_LOG_D(TAG, "Available buff size: %ld", buff_free_size);
  116. furi_check(furi_mutex_release(seos_svc->buff_size_mtx) == FuriStatusOk);
  117. } else {
  118. FURI_LOG_W(TAG, "No seos_cvs->callback defined");
  119. }
  120. ret = BleEventAckFlowEnable;
  121. }
  122. } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
  123. FURI_LOG_T(TAG, "Ack received");
  124. if(seos_svc->callback) {
  125. SeosServiceEvent event = {
  126. .event = SeosServiceEventTypeDataSent,
  127. };
  128. seos_svc->callback(event, seos_svc->context);
  129. }
  130. ret = BleEventAckFlowEnable;
  131. } else {
  132. FURI_LOG_D(
  133. TAG,
  134. "ble_svc_seos_event_handler unhandled blecore_evt->ecode %d",
  135. blecore_evt->ecode);
  136. }
  137. } else {
  138. FURI_LOG_D(
  139. TAG, "ble_svc_seos_event_handler unhandled event_pckt->evt %d", event_pckt->evt);
  140. }
  141. return ret;
  142. }
  143. BleServiceSeos* ble_svc_seos_start(void) {
  144. BleServiceSeos* seos_svc = malloc(sizeof(BleServiceSeos));
  145. seos_svc->event_handler =
  146. ble_event_dispatcher_register_svc_handler(ble_svc_seos_event_handler, seos_svc);
  147. if(!ble_gatt_service_add(
  148. UUID_TYPE_128, &service_uuid, PRIMARY_SERVICE, 12, &seos_svc->svc_handle)) {
  149. free(seos_svc);
  150. return NULL;
  151. }
  152. for(uint8_t i = 0; i < SeosSvcGattCharacteristicCount; i++) {
  153. ble_gatt_characteristic_init(
  154. seos_svc->svc_handle, &ble_svc_seos_chars[i], &seos_svc->chars[i]);
  155. }
  156. seos_svc->buff_size_mtx = furi_mutex_alloc(FuriMutexTypeNormal);
  157. return seos_svc;
  158. }
  159. void ble_svc_seos_set_callbacks(
  160. BleServiceSeos* seos_svc,
  161. uint16_t buff_size,
  162. SeosServiceEventCallback callback,
  163. void* context) {
  164. furi_check(seos_svc);
  165. seos_svc->callback = callback;
  166. seos_svc->context = context;
  167. seos_svc->buff_size = buff_size;
  168. seos_svc->bytes_ready_to_receive = buff_size;
  169. }
  170. void ble_svc_seos_stop(BleServiceSeos* seos_svc) {
  171. furi_check(seos_svc);
  172. ble_event_dispatcher_unregister_svc_handler(seos_svc->event_handler);
  173. for(uint8_t i = 0; i < SeosSvcGattCharacteristicCount; i++) {
  174. ble_gatt_characteristic_delete(seos_svc->svc_handle, &seos_svc->chars[i]);
  175. }
  176. ble_gatt_service_delete(seos_svc->svc_handle);
  177. furi_mutex_free(seos_svc->buff_size_mtx);
  178. free(seos_svc);
  179. }
  180. bool ble_svc_seos_update_tx(BleServiceSeos* seos_svc, uint8_t* data, uint16_t data_len) {
  181. if(data_len > BLE_SVC_SEOS_DATA_LEN_MAX) {
  182. return false;
  183. }
  184. SeosSvcDataWrapper report_data = {.data_ptr = data, .data_len = data_len};
  185. ble_gatt_characteristic_update(
  186. seos_svc->svc_handle, &seos_svc->chars[SeosSvcGattCharacteristicRxTx], &report_data);
  187. return true;
  188. }