Browse Source

basic ble notification support

Thomas Buck 6 months ago
parent
commit
944f87e56b
2 changed files with 167 additions and 1 deletions
  1. 5
    0
      include/ble.h
  2. 162
    1
      src/ble.c

+ 5
- 0
include/ble.h View File

60
 int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
60
 int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
61
                  const uint8_t *buff, uint16_t buff_len);
61
                  const uint8_t *buff, uint16_t buff_len);
62
 
62
 
63
+int8_t ble_notification_disable(const uint8_t *service, const uint8_t *characteristic);
64
+int8_t ble_notification_enable(const uint8_t *service, const uint8_t *characteristic);
65
+bool ble_notification_ready(void);
66
+uint16_t ble_notification_get(uint8_t *buff, uint16_t buff_len);
67
+
63
 #endif // __BLE_H__
68
 #endif // __BLE_H__

+ 162
- 1
src/ble.c View File

32
 #define BLE_SRVC_TIMEOUT_MS (3 * 500)
32
 #define BLE_SRVC_TIMEOUT_MS (3 * 500)
33
 #define BLE_CHAR_TIMEOUT_MS (3 * 2000)
33
 #define BLE_CHAR_TIMEOUT_MS (3 * 2000)
34
 #define BLE_WRTE_TIMEOUT_MS (3 * 500)
34
 #define BLE_WRTE_TIMEOUT_MS (3 * 500)
35
+#define BLE_NOTY_TIMEOUT_MS (3 * 500)
35
 #define BLE_MAX_SCAN_AGE_MS (10 * 1000)
36
 #define BLE_MAX_SCAN_AGE_MS (10 * 1000)
36
 #define BLE_MAX_SERVICES 8
37
 #define BLE_MAX_SERVICES 8
37
 #define BLE_MAX_CHARACTERISTICS 8
38
 #define BLE_MAX_CHARACTERISTICS 8
48
     TC_W4_CHARACTERISTIC,
49
     TC_W4_CHARACTERISTIC,
49
     TC_W4_WRITE,
50
     TC_W4_WRITE,
50
     TC_WRITE_COMPLETE,
51
     TC_WRITE_COMPLETE,
52
+    TC_W4_NOTIFY_ENABLE,
53
+    TC_NOTIFY_ENABLED,
51
 };
54
 };
52
 
55
 
53
 struct ble_characteristic {
56
 struct ble_characteristic {
54
     bool set;
57
     bool set;
55
     gatt_client_characteristic_t c;
58
     gatt_client_characteristic_t c;
59
+    gatt_client_notification_t n;
56
 };
60
 };
57
 
61
 
58
 struct ble_service {
62
 struct ble_service {
319
             state = TC_WRITE_COMPLETE;
323
             state = TC_WRITE_COMPLETE;
320
             break;
324
             break;
321
 
325
 
326
+        case TC_W4_NOTIFY_ENABLE:
327
+            //debug("notify enable complete");
328
+            state = TC_NOTIFY_ENABLED;
329
+            break;
330
+
322
         default:
331
         default:
323
             debug("gatt query complete in invalid state %d", state);
332
             debug("gatt query complete in invalid state %d", state);
324
             break;
333
             break;
326
         break;
335
         break;
327
     }
336
     }
328
 
337
 
338
+    case GATT_EVENT_NOTIFICATION: {
339
+        if ((state != TC_READY) && (state != TC_WRITE_COMPLETE)) {
340
+            debug("gatt notification in invalid state %d", state);
341
+            return;
342
+        }
343
+
344
+        uint16_t value_length = gatt_event_notification_get_value_length(packet);
345
+        const uint8_t *value = gatt_event_notification_get_value(packet);
346
+        if ((read_len + value_length) <= BLE_MAX_VALUE_LEN) {
347
+            memcpy(data_buff + read_len, value, value_length);
348
+            read_len += value_length;
349
+        }
350
+
351
+        break;
352
+    }
353
+
329
     default:
354
     default:
330
         //debug("unexpected event 0x%02X", hci_event_packet_get_type(packet));
355
         //debug("unexpected event 0x%02X", hci_event_packet_get_type(packet));
331
         break;
356
         break;
572
 
597
 
573
     memcpy(buff, data_buff, read_len);
598
     memcpy(buff, data_buff, read_len);
574
 
599
 
600
+    uint16_t tmp = read_len;
601
+    read_len = 0;
602
+
575
     cyw43_thread_exit();
603
     cyw43_thread_exit();
576
-    return read_len;
604
+    return tmp;
577
 }
605
 }
578
 
606
 
579
 static int discover_service(const uint8_t *service) {
607
 static int discover_service(const uint8_t *service) {
813
     cyw43_thread_exit();
841
     cyw43_thread_exit();
814
     return 0;
842
     return 0;
815
 }
843
 }
844
+
845
+int8_t ble_notification_disable(const uint8_t *service, const uint8_t *characteristic) {
846
+    cyw43_thread_enter();
847
+
848
+    if (state != TC_READY) {
849
+        cyw43_thread_exit();
850
+        debug("invalid state for notify (%d)", state);
851
+        return -1;
852
+    }
853
+
854
+    int srvc = discover_service(service);
855
+    if (srvc < 0) {
856
+        debug("error discovering service (%d)", srvc);
857
+        return srvc;
858
+    }
859
+
860
+    int ch = discover_characteristic(srvc, characteristic);
861
+    if (ch < 0) {
862
+        debug("error discovering characteristic (%d)", ch);
863
+        return ch;
864
+    }
865
+
866
+    gatt_client_stop_listening_for_characteristic_value_updates(&services[srvc].chars[ch].n);
867
+
868
+    cyw43_thread_exit();
869
+    return 0;
870
+}
871
+
872
+int8_t ble_notification_enable(const uint8_t *service, const uint8_t *characteristic) {
873
+    cyw43_thread_enter();
874
+
875
+    if (state != TC_READY) {
876
+        cyw43_thread_exit();
877
+        debug("invalid state for notify (%d)", state);
878
+        return -1;
879
+    }
880
+
881
+    int srvc = discover_service(service);
882
+    if (srvc < 0) {
883
+        debug("error discovering service (%d)", srvc);
884
+        return srvc;
885
+    }
886
+
887
+    int ch = discover_characteristic(srvc, characteristic);
888
+    if (ch < 0) {
889
+        debug("error discovering characteristic (%d)", ch);
890
+        return ch;
891
+    }
892
+
893
+    gatt_client_listen_for_characteristic_value_updates(&services[srvc].chars[ch].n,
894
+                                                        hci_event_handler,
895
+                                                        connection_handle,
896
+                                                        &services[srvc].chars[ch].c);
897
+
898
+    gatt_client_write_client_characteristic_configuration(hci_event_handler,
899
+                                                          connection_handle,
900
+                                                          &services[srvc].chars[ch].c,
901
+                                                          GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
902
+
903
+    state = TC_W4_NOTIFY_ENABLE;
904
+    cyw43_thread_exit();
905
+
906
+    uint32_t start_time = to_ms_since_boot(get_absolute_time());
907
+    while (1) {
908
+        sleep_ms(1);
909
+        main_loop_hw();
910
+
911
+        uint32_t now = to_ms_since_boot(get_absolute_time());
912
+        if ((now - start_time) >= BLE_NOTY_TIMEOUT_MS) {
913
+            debug("timeout waiting for notify enable");
914
+            cyw43_thread_enter();
915
+            state = TC_READY;
916
+            cyw43_thread_exit();
917
+            return -6;
918
+        }
919
+
920
+        cyw43_thread_enter();
921
+        enum ble_state state_cached = state;
922
+        cyw43_thread_exit();
923
+
924
+        if ((state_cached == TC_NOTIFY_ENABLED) || (state_cached == TC_READY)) {
925
+            break;
926
+        }
927
+    }
928
+
929
+    cyw43_thread_enter();
930
+
931
+    int8_t ret = (state == TC_NOTIFY_ENABLED) ? 0 : -7;
932
+    state = TC_READY;
933
+
934
+    cyw43_thread_exit();
935
+    return ret;
936
+}
937
+
938
+bool ble_notification_ready(void) {
939
+    cyw43_thread_enter();
940
+
941
+    if (state != TC_READY) {
942
+        cyw43_thread_exit();
943
+        debug("invalid state for notify (%d)", state);
944
+        return -1;
945
+    }
946
+
947
+    uint16_t tmp = read_len;
948
+
949
+    cyw43_thread_exit();
950
+    return (tmp > 0);
951
+
952
+}
953
+
954
+uint16_t ble_notification_get(uint8_t *buff, uint16_t buff_len) {
955
+    cyw43_thread_enter();
956
+
957
+    if (state != TC_READY) {
958
+        cyw43_thread_exit();
959
+        debug("invalid state for notify (%d)", state);
960
+        return -1;
961
+    }
962
+
963
+    if (read_len > buff_len) {
964
+        debug("buffer too short (%d < %d)", buff_len, read_len);
965
+        cyw43_thread_exit();
966
+        return -2;
967
+    }
968
+
969
+    memcpy(buff, data_buff, read_len);
970
+
971
+    uint16_t tmp = read_len;
972
+    read_len = 0;
973
+
974
+    cyw43_thread_exit();
975
+    return tmp;
976
+}

Loading…
Cancel
Save