Просмотр исходного кода

detect known device types and read their serial number

Thomas Buck 1 год назад
Родитель
Сommit
00e30acf5d
7 измененных файлов: 150 добавлений и 25 удалений
  1. 1
    0
      CMakeLists.txt
  2. 3
    0
      include/ble.h
  3. 33
    0
      include/models.h
  4. 47
    22
      src/ble.c
  5. 10
    3
      src/console.c
  6. 53
    0
      src/models.c
  7. 3
    0
      src/state.c

+ 1
- 0
CMakeLists.txt Просмотреть файл

@@ -63,6 +63,7 @@ target_sources(gadget PUBLIC
63 63
     src/volcano.c
64 64
     src/serial.c
65 65
     src/ring.c
66
+    src/models.c
66 67
 
67 68
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ff.c
68 69
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ffunicode.c

+ 3
- 0
include/ble.h Просмотреть файл

@@ -22,6 +22,7 @@
22 22
 #include "btstack.h"
23 23
 
24 24
 #define BLE_MAX_NAME_LENGTH 32
25
+#define BLE_MAX_DATA_LENGTH 26
25 26
 #define BLE_MAX_SCAN_RESULTS 32
26 27
 #define BLE_MAX_VALUE_LEN 64
27 28
 
@@ -39,6 +40,8 @@ struct ble_scan_result {
39 40
     bd_addr_type_t type;
40 41
     int8_t rssi;
41 42
     char name[BLE_MAX_NAME_LENGTH + 1];
43
+    uint8_t data[BLE_MAX_DATA_LENGTH];
44
+    size_t data_len;
42 45
 };
43 46
 
44 47
 void ble_init(void);

+ 33
- 0
include/models.h Просмотреть файл

@@ -0,0 +1,33 @@
1
+/*
2
+ * models.h
3
+ *
4
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#ifndef __MODELS_H__
20
+#define __MODELS_H__
21
+
22
+#include <stdint.h>
23
+
24
+enum known_devices {
25
+    DEV_UNKNOWN = 0,
26
+    DEV_VOLCANO,
27
+    DEV_CRAFTY,
28
+};
29
+
30
+enum known_devices models_filter_name(const char *name);
31
+int8_t models_get_serial(const uint8_t *data, size_t data_len, char *buff, size_t buff_len);
32
+
33
+#endif // __MODELS_H__

+ 47
- 22
src/ble.c Просмотреть файл

@@ -24,6 +24,7 @@
24 24
 
25 25
 #include "config.h"
26 26
 #include "log.h"
27
+#include "main.h"
27 28
 #include "util.h"
28 29
 #include "ble.h"
29 30
 
@@ -104,6 +105,7 @@ static void hci_add_scan_result(bd_addr_t addr, bd_addr_type_t type, int8_t rssi
104 105
     scans[unused].type = type;
105 106
     scans[unused].rssi = rssi;
106 107
     scans[unused].name[0] = '\0';
108
+    scans[unused].data_len = 0;
107 109
 }
108 110
 
109 111
 static void hci_scan_result_add_name(bd_addr_t addr, const uint8_t *data, uint8_t data_size) {
@@ -128,6 +130,28 @@ static void hci_scan_result_add_name(bd_addr_t addr, const uint8_t *data, uint8_
128 130
     debug("no matching entry for %s to add name '%.*s' to", bd_addr_to_str(addr), data_size, data);
129 131
 }
130 132
 
133
+static void hci_scan_result_add_data(bd_addr_t addr, const uint8_t *data, uint8_t data_size) {
134
+    for (uint i = 0; i < BLE_MAX_SCAN_RESULTS; i++) {
135
+        if (!scans[i].set) {
136
+            continue;
137
+        }
138
+        if (memcmp(addr, scans[i].addr, sizeof(bd_addr_t)) != 0) {
139
+            continue;
140
+        }
141
+
142
+        uint8_t len = data_size;
143
+        if (len > BLE_MAX_DATA_LENGTH) {
144
+            len = BLE_MAX_DATA_LENGTH;
145
+        }
146
+        memcpy(scans[i].data, data, len);
147
+        scans[i].data_len = len;
148
+        scans[i].time = to_ms_since_boot(get_absolute_time());
149
+        return;
150
+    }
151
+
152
+    debug("no matching entry for %s to add data to", bd_addr_to_str(addr));
153
+}
154
+
131 155
 static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
132 156
     UNUSED(size);
133 157
     UNUSED(channel);
@@ -189,6 +213,18 @@ static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
189 213
                 hci_scan_result_add_name(addr, data, data_size);
190 214
                 break;
191 215
 
216
+            case BLUETOOTH_DATA_TYPE_SERVICE_DATA:
217
+            case BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA:
218
+                // TODO ugly
219
+                if (data_size == 12) {
220
+                    // Crafty+
221
+                    hci_scan_result_add_data(addr, data, data_size);
222
+                } else if (data_size == 26) {
223
+                    // Volcano
224
+                    hci_scan_result_add_data(addr, data, data_size);
225
+                }
226
+                break;
227
+
192 228
             default:
193 229
                 //debug("Unexpected advertisement type 0x%02X from %s", data_type, bd_addr_to_str(addr));
194 230
                 //hexdump(data, data_size);
@@ -399,10 +435,13 @@ int32_t ble_get_scan_results(struct ble_scan_result *buf, uint16_t len) {
399 435
             continue;
400 436
         }
401 437
 
402
-        uint32_t diff = to_ms_since_boot(get_absolute_time()) - scans[i].time;
403
-        if (diff >= BLE_MAX_SCAN_AGE_MS) {
404
-            //debug("removing %s due to age", bd_addr_to_str(scans[i].addr));
405
-            scans[i].set = false;
438
+        // only age out entries while scanning, otherwise keep results cached
439
+        if (state == TC_W4_SCAN) {
440
+            uint32_t diff = to_ms_since_boot(get_absolute_time()) - scans[i].time;
441
+            if (diff >= BLE_MAX_SCAN_AGE_MS) {
442
+                //debug("removing %s due to age", bd_addr_to_str(scans[i].addr));
443
+                scans[i].set = false;
444
+            }
406 445
         }
407 446
 
408 447
         memcpy(buf + pos, scans + i, sizeof(struct ble_scan_result));
@@ -497,15 +536,13 @@ int32_t ble_read(const uint8_t *characteristic, uint8_t *buff, uint16_t buff_len
497 536
     uint32_t start_time = to_ms_since_boot(get_absolute_time());
498 537
     while (1) {
499 538
         sleep_ms(1);
539
+        main_loop_hw();
500 540
 
501 541
         uint32_t now = to_ms_since_boot(get_absolute_time());
502 542
         if ((now - start_time) >= BLE_READ_TIMEOUT_MS) {
503 543
             debug("timeout waiting for read");
504 544
             return -3;
505 545
         }
506
-#if BLE_READ_TIMEOUT_MS >= (WATCHDOG_PERIOD_MS / 2)
507
-        watchdog_update();
508
-#endif
509 546
 
510 547
         cyw43_thread_enter();
511 548
         enum ble_state state_cached = state;
@@ -585,15 +622,13 @@ int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
585 622
         uint32_t start_time = to_ms_since_boot(get_absolute_time());
586 623
         while (1) {
587 624
             sleep_ms(1);
625
+            main_loop_hw();
588 626
 
589 627
             uint32_t now = to_ms_since_boot(get_absolute_time());
590 628
             if ((now - start_time) >= BLE_SRVC_TIMEOUT_MS) {
591 629
                 debug("timeout waiting for service");
592 630
                 return -3;
593 631
             }
594
-#if BLE_SRVC_TIMEOUT_MS >= (WATCHDOG_PERIOD_MS / 2)
595
-            watchdog_update();
596
-#endif
597 632
 
598 633
             cyw43_thread_enter();
599 634
             enum ble_state state_cached = state;
@@ -604,9 +639,6 @@ int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
604 639
             }
605 640
         }
606 641
 
607
-        // allow some time for service discovery
608
-        watchdog_update();
609
-
610 642
         cyw43_thread_enter();
611 643
     }
612 644
 
@@ -654,15 +686,13 @@ int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
654 686
         uint32_t start_time = to_ms_since_boot(get_absolute_time());
655 687
         while (1) {
656 688
             sleep_ms(1);
689
+            main_loop_hw();
657 690
 
658 691
             uint32_t now = to_ms_since_boot(get_absolute_time());
659 692
             if ((now - start_time) >= BLE_CHAR_TIMEOUT_MS) {
660 693
                 debug("timeout waiting for characteristic");
661 694
                 return -5;
662 695
             }
663
-#if BLE_CHAR_TIMEOUT_MS >= (WATCHDOG_PERIOD_MS / 2)
664
-            watchdog_update();
665
-#endif
666 696
 
667 697
             cyw43_thread_enter();
668 698
             enum ble_state state_cached = state;
@@ -673,9 +703,6 @@ int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
673 703
             }
674 704
         }
675 705
 
676
-        // allow some time for characteristic discovery
677
-        watchdog_update();
678
-
679 706
         cyw43_thread_enter();
680 707
     }
681 708
 
@@ -700,15 +727,13 @@ int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
700 727
     uint32_t start_time = to_ms_since_boot(get_absolute_time());
701 728
     while (1) {
702 729
         sleep_ms(1);
730
+        main_loop_hw();
703 731
 
704 732
         uint32_t now = to_ms_since_boot(get_absolute_time());
705 733
         if ((now - start_time) >= BLE_WRTE_TIMEOUT_MS) {
706 734
             debug("timeout waiting for write");
707 735
             return -7;
708 736
         }
709
-#if BLE_WRTE_TIMEOUT_MS >= (WATCHDOG_PERIOD_MS / 2)
710
-        watchdog_update();
711
-#endif
712 737
 
713 738
         cyw43_thread_enter();
714 739
         enum ble_state state_cached = state;

+ 10
- 3
src/console.c Просмотреть файл

@@ -30,7 +30,6 @@
30 30
 #include "usb_cdc.h"
31 31
 #include "usb_msc.h"
32 32
 #include "debug_disk.h"
33
-#include "console.h"
34 33
 #include "lipo.h"
35 34
 #include "ble.h"
36 35
 #include "text.h"
@@ -39,6 +38,8 @@
39 38
 #include "volcano.h"
40 39
 #include "serial.h"
41 40
 #include "main.h"
41
+#include "models.h"
42
+#include "console.h"
42 43
 
43 44
 #define CNSL_BUFF_SIZE 64
44 45
 #define CNSL_REPEAT_MS 500
@@ -141,11 +142,17 @@ static void cnsl_interpret(const char *line) {
141 142
         } else {
142 143
             println("%d results", n);
143 144
             for (int i = 0; i < n; i++) {
145
+                char info[32] = "";
146
+                enum known_devices dev = models_filter_name(results[i].name);
147
+                if (dev != DEV_UNKNOWN) {
148
+                    models_get_serial(results[i].data, results[i].data_len,
149
+                                      info, sizeof(info));
150
+                }
144 151
                 uint32_t age = to_ms_since_boot(get_absolute_time()) - results[i].time;
145
-                println("addr=%s type=%d rssi=%d age=%.1fs name='%s'",
152
+                println("addr=%s type=%d rssi=%d age=%.1fs name='%s' info='%s'",
146 153
                         bd_addr_to_str(results[i].addr),
147 154
                         results[i].type, results[i].rssi,
148
-                        age / 1000.0, results[i].name);
155
+                        age / 1000.0, results[i].name, info);
149 156
             }
150 157
         }
151 158
     } else if (str_startswith(line, "con ")) {

+ 53
- 0
src/models.c Просмотреть файл

@@ -0,0 +1,53 @@
1
+/*
2
+ * models.c
3
+ *
4
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#include <stddef.h>
20
+#include <string.h>
21
+
22
+#include "config.h"
23
+#include "log.h"
24
+#include "util.h"
25
+#include "models.h"
26
+
27
+enum known_devices models_filter_name(const char *name) {
28
+    if (name == NULL) {
29
+        return DEV_UNKNOWN;
30
+    } else if (strcmp(name, "S&B VOLCANO H") == 0) {
31
+        return DEV_VOLCANO;
32
+    } else if (strcmp(name, "STORZ&BICKEL") == 0) {
33
+        return DEV_VOLCANO;
34
+    } else {
35
+        return DEV_UNKNOWN;
36
+    }
37
+}
38
+
39
+int8_t models_get_serial(const uint8_t *data, size_t data_len, char *buff, size_t buff_len) {
40
+    if ((data == NULL) || (data_len <= 0) || (buff == NULL) || (buff_len <= 0)) {
41
+        return -1;
42
+    }
43
+
44
+    const size_t serial_len = 8;
45
+    const size_t serial_off = 2;
46
+    if ((data_len < (serial_len + serial_off)) || (buff_len < (serial_len + 1))) {
47
+        return -2;
48
+    }
49
+    memcpy(buff, data + serial_off, serial_len);
50
+    buff[serial_len] = '\0';
51
+
52
+    return 0;
53
+}

+ 3
- 0
src/state.c Просмотреть файл

@@ -90,6 +90,9 @@ void state_run(void) {
90 90
     };
91 91
 
92 92
     switch (state) {
93
+    case STATE_INIT:
94
+        break;
95
+
93 96
     case STATE_SCAN: {
94 97
         struct ble_scan_result results[BLE_MAX_SCAN_RESULTS] = {0};
95 98
         int n = ble_get_scan_results(results, BLE_MAX_SCAN_RESULTS);

Загрузка…
Отмена
Сохранить