Browse Source

open ap when no successful wifi connection

Thomas Buck 11 months ago
parent
commit
4c9ccdbefa
7 changed files with 120 additions and 16 deletions
  1. 4
    0
      CMakeLists.txt
  2. 1
    0
      README.md
  3. 4
    0
      include/usb_descriptors.h
  4. 2
    2
      src/ota_shim.c
  5. 1
    0
      src/state_about.c
  6. 8
    1
      src/usb_descriptors.c
  7. 100
    13
      src/wifi.c

+ 4
- 0
CMakeLists.txt View File

@@ -129,6 +129,8 @@ target_sources(gadget PUBLIC
129 129
     mcufont/decoder/mf_bwfont.c
130 130
     mcufont/decoder/mf_scaledfont.c
131 131
     mcufont/decoder/mf_wordwrap.c
132
+
133
+    picowota/dhcpserver/dhcpserver.c
132 134
 )
133 135
 
134 136
 # external dependency include directories
@@ -141,6 +143,7 @@ target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/mcufont/decod
141 143
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/data)
142 144
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/build)
143 145
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
146
+target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/picowota/dhcpserver)
144 147
 
145 148
 # compress source code and stuff we want to include
146 149
 add_custom_target(pack bash -c "./pack_data.sh ${CMAKE_CURRENT_BINARY_DIR}"
@@ -211,6 +214,7 @@ set(PICOWOTA_ADDITIONAL_SOURCES
211 214
     ${CMAKE_CURRENT_SOURCE_DIR}/src/workflow_default.c
212 215
     ${CMAKE_CURRENT_SOURCE_DIR}/src/buttons.c
213 216
     ${CMAKE_CURRENT_SOURCE_DIR}/src/util.c
217
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
214 218
 
215 219
     ${CMAKE_CURRENT_SOURCE_DIR}/st7789/src/driver_st7789.c
216 220
 

+ 1
- 0
README.md View File

@@ -124,6 +124,7 @@ And the project uses the [FatFS library](https://github.com/abbrev/fatfs), licen
124 124
 Also included are the [MCUFont library](https://github.com/mcufont/mcufont) and the [st7789 library](https://github.com/hepingood/st7789), both licensed under the MIT license.
125 125
 It also uses the [BTstack](https://github.com/bluekitchen/btstack/blob/master/LICENSE) included with the Pico SDK, following their [license terms](https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/pico_btstack/LICENSE.RP).
126 126
 The included bootloader is [picowota](https://github.com/usedbytes/picowota), licensed as BSD 3-clause.
127
+I'm also using the MicroPython DHCP server, licensed as MIT and included with picowota.
127 128
 
128 129
 The case design is also licensed as GPLv3.
129 130
 It uses a [Pi Pico case model](https://www.printables.com/model/210898-raspberry-pi-pico-case) licensed as CC-BY-NC-SA.

+ 4
- 0
include/usb_descriptors.h View File

@@ -19,6 +19,10 @@
19 19
 #ifndef USB_DESCRIPTORS_H_
20 20
 #define USB_DESCRIPTORS_H_
21 21
 
22
+#include "pico/unique_id.h"
23
+
24
+extern char string_pico_serial[2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1];
25
+
22 26
 void usb_descriptor_init_id(void);
23 27
 
24 28
 #endif /* USB_DESCRIPTORS_H_ */

+ 2
- 2
src/ota_shim.c View File

@@ -29,6 +29,7 @@
29 29
 #include "textbox.h"
30 30
 #include "mem.h"
31 31
 #include "util.h"
32
+#include "usb_descriptors.h"
32 33
 #include "wifi.h"
33 34
 
34 35
 static int16_t lcd_off = 0;
@@ -113,6 +114,7 @@ void picowota_poll(void) {
113 114
 }
114 115
 
115 116
 int picowota_init(void) {
117
+    usb_descriptor_init_id();
116 118
     buttons_init();
117 119
     buttons_callback(ota_buttons);
118 120
     mem_load();
@@ -144,8 +146,6 @@ int picowota_init(void) {
144 146
         }
145 147
 
146 148
         picowota_poll();
147
-
148
-        // TODO open AP when timed out?
149 149
     }
150 150
 
151 151
     debug("wifi ready");

+ 1
- 0
src/state_about.c View File

@@ -55,6 +55,7 @@ static const char *about_text =
55 55
     "hepingood/st7789\n"
56 56
     "usedbytes/picowota\n"
57 57
     "lwip-tcpip/lwip\n"
58
+    "micropython/dhcpserver\n"
58 59
     "\n"
59 60
 
60 61
     "This program is free software: you can redistribute it and/or modify "

+ 8
- 1
src/usb_descriptors.c View File

@@ -27,12 +27,13 @@
27 27
  *
28 28
  */
29 29
 
30
-#include "pico/unique_id.h"
31 30
 #include "tusb.h"
32 31
 
33 32
 #include "config.h"
34 33
 #include "usb_descriptors.h"
35 34
 
35
+#ifndef PICOWOTA
36
+
36 37
 /*
37 38
  * A combination of interfaces must have a unique product id,
38 39
  * since PC will save device driver after the first plug.
@@ -172,6 +173,8 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index) {
172 173
     return desc_configuration;
173 174
 }
174 175
 
176
+#endif // PICOWOTA
177
+
175 178
 //--------------------------------------------------------------------+
176 179
 // String Descriptors
177 180
 //--------------------------------------------------------------------+
@@ -182,6 +185,8 @@ void usb_descriptor_init_id(void) {
182 185
     pico_get_unique_board_id_string(string_pico_serial, sizeof(string_pico_serial));
183 186
 }
184 187
 
188
+#ifndef PICOWOTA
189
+
185 190
 // array of pointer to string descriptors
186 191
 char const* string_desc_arr [] = {
187 192
     (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
@@ -227,3 +232,5 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
227 232
 
228 233
     return _desc_str;
229 234
 }
235
+
236
+#endif // PICOWOTA

+ 100
- 13
src/wifi.c View File

@@ -19,13 +19,22 @@
19 19
 #include "pico/cyw43_arch.h"
20 20
 #include "lwip/netif.h"
21 21
 #include "lwip/ip4_addr.h"
22
+#include "dhcpserver.h"
22 23
 
23 24
 #include "config.h"
24 25
 #include "log.h"
25 26
 #include "mem.h"
27
+#include "usb_descriptors.h"
26 28
 #include "wifi.h"
27 29
 
28
-#define CONNECT_TIMEOUT (5 * 1000)
30
+#define CONNECT_TIMEOUT_MS (8UL * 1000UL)
31
+#define SCAN_AP_TIMEOUT_MS (20UL * 1000UL)
32
+
33
+#define WIFI_AP_SSID_PREFIX "Volcano-"
34
+#define WIFI_AP_SSID_LEN 4
35
+#define WIFI_AP_PASS_LEN 8
36
+static_assert((WIFI_AP_SSID_LEN + WIFI_AP_PASS_LEN) <= (2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES),
37
+              "SSID and Password parts for AP need to fit Pico serial number");
29 38
 
30 39
 enum wifi_state {
31 40
     WS_IDLE = 0,
@@ -36,12 +45,58 @@ enum wifi_state {
36 45
 };
37 46
 
38 47
 static enum wifi_state state = WS_IDLE;
39
-static uint32_t start_time = 0;
48
+static uint32_t start_scan_time = 0;
49
+static uint32_t start_connect_time = 0;
50
+static uint32_t start_ip_time = 0;
51
+static dhcp_server_t dhcp_server;
52
+static bool enabled_ap = false;
53
+static char curr_ssid[WIFI_MAX_NAME_LEN + 1] = {0};
54
+static char curr_pass[WIFI_MAX_PASS_LEN + 1] = {0};
55
+
56
+static void wifi_ap(void) {
57
+    cyw43_thread_enter();
58
+
59
+    // last N chars of serial for ssid and password
60
+    const size_t prefix_len = strlen(WIFI_AP_SSID_PREFIX);
61
+    char wifi_ssid[prefix_len + WIFI_AP_SSID_LEN + 1];
62
+    memcpy(wifi_ssid, WIFI_AP_SSID_PREFIX, prefix_len);
63
+    memcpy(wifi_ssid + prefix_len,
64
+           string_pico_serial + (2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES) - WIFI_AP_SSID_LEN,
65
+           WIFI_AP_SSID_LEN);
66
+    wifi_ssid[prefix_len + WIFI_AP_SSID_LEN] = '\0';
67
+    strncpy(curr_ssid, wifi_ssid, WIFI_MAX_NAME_LEN);
68
+
69
+    char wifi_pass[WIFI_AP_PASS_LEN + 1] = {0};
70
+    memcpy(wifi_pass,
71
+           string_pico_serial + (2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES) - WIFI_AP_SSID_LEN - WIFI_AP_PASS_LEN,
72
+           WIFI_AP_PASS_LEN);
73
+    strncpy(curr_pass, wifi_pass, WIFI_MAX_PASS_LEN);
74
+
75
+    debug("disable sta");
76
+    cyw43_arch_disable_sta_mode();
77
+
78
+    debug("enable ap '%s' '%s'", wifi_ssid, wifi_pass);
79
+    cyw43_arch_enable_ap_mode(wifi_ssid, wifi_pass, CYW43_AUTH_WPA2_AES_PSK);
80
+
81
+    ip4_addr_t gw, mask;
82
+    IP4_ADDR(&gw, 192, 168, 4, 1);
83
+    IP4_ADDR(&mask, 255, 255, 255, 0);
84
+
85
+    debug("enable dhcp");
86
+    dhcp_server_init(&dhcp_server, &gw, &mask);
87
+
88
+    state = WS_READY;
89
+    enabled_ap = true;
90
+
91
+    cyw43_thread_exit();
92
+}
40 93
 
41 94
 static void wifi_connect(const char *ssid, const char *pw, uint32_t auth) {
95
+    cyw43_thread_enter();
96
+
42 97
     debug("connecting to '%s'", ssid);
43
-    start_time = to_ms_since_boot(get_absolute_time());
44
-    state = WS_CONNECT;
98
+    strncpy(curr_ssid, ssid, WIFI_MAX_NAME_LEN);
99
+    strncpy(curr_pass, pw, WIFI_MAX_PASS_LEN);
45 100
 
46 101
     // https://github.com/raspberrypi/pico-sdk/issues/1413
47 102
     uint32_t a = 0;
@@ -55,7 +110,12 @@ static void wifi_connect(const char *ssid, const char *pw, uint32_t auth) {
55 110
     if (r != 0) {
56 111
         debug("failed to connect %d", r);
57 112
         state = WS_SCAN;
113
+    } else {
114
+        start_connect_time = to_ms_since_boot(get_absolute_time());
115
+        state = WS_CONNECT;
58 116
     }
117
+
118
+    cyw43_thread_exit();
59 119
 }
60 120
 
61 121
 static int scan_result(void *env, const cyw43_ev_scan_result_t *result) {
@@ -96,15 +156,27 @@ void wifi_init(void) {
96 156
     }
97 157
 
98 158
     cyw43_thread_enter();
159
+
99 160
     cyw43_arch_enable_sta_mode();
161
+
100 162
     wifi_scan();
163
+    start_scan_time = to_ms_since_boot(get_absolute_time());
164
+
101 165
     cyw43_thread_exit();
102 166
 }
103 167
 
104 168
 void wifi_deinit(void) {
105 169
     cyw43_thread_enter();
170
+
106 171
     cyw43_arch_disable_sta_mode();
172
+    cyw43_arch_disable_ap_mode();
107 173
     state = WS_IDLE;
174
+
175
+    if (enabled_ap) {
176
+        enabled_ap = false;
177
+        dhcp_server_deinit(&dhcp_server);
178
+    }
179
+
108 180
     cyw43_thread_exit();
109 181
 }
110 182
 
@@ -131,11 +203,21 @@ const char *wifi_state(void) {
131 203
         return "Waiting for IP";
132 204
 
133 205
     case WS_READY: {
134
-        cyw43_arch_lwip_begin();
135
-        const ip4_addr_t *ip = netif_ip4_addr(netif_default);
136
-        cyw43_arch_lwip_end();
137
-
138
-        return ip4addr_ntoa(ip);
206
+        uint32_t now = to_ms_since_boot(get_absolute_time()) % (enabled_ap ? 9000 : 6000);
207
+        if (now < 3000) {
208
+            // show SSID
209
+            return curr_ssid;
210
+        } else if (now < 6000) {
211
+            // show IP
212
+            cyw43_arch_lwip_begin();
213
+            const ip4_addr_t *ip = netif_ip4_addr(netif_default);
214
+            cyw43_arch_lwip_end();
215
+
216
+            return ip4addr_ntoa(ip);
217
+        } else {
218
+            // show Pass (only AP)
219
+            return curr_pass;
220
+        }
139 221
     }
140 222
     }
141 223
 
@@ -150,6 +232,12 @@ void wifi_run(void) {
150 232
             debug("restarting scan");
151 233
             wifi_scan();
152 234
         }
235
+
236
+        uint32_t now = to_ms_since_boot(get_absolute_time());
237
+        if ((now - start_scan_time) >= SCAN_AP_TIMEOUT_MS) {
238
+            debug("wifi sta timeout. opening ap.");
239
+            wifi_ap();
240
+        }
153 241
     } else if (state == WS_CONNECT) {
154 242
         int link = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA);
155 243
 
@@ -161,7 +249,7 @@ void wifi_run(void) {
161 249
 
162 250
         if (link == CYW43_LINK_JOIN) {
163 251
             debug("joined network");
164
-            start_time = to_ms_since_boot(get_absolute_time());
252
+            start_ip_time = to_ms_since_boot(get_absolute_time());
165 253
             state = WS_WAIT_FOR_IP;
166 254
         } else if (link < CYW43_LINK_DOWN) {
167 255
             debug("net connection failed. retry.");
@@ -169,7 +257,7 @@ void wifi_run(void) {
169 257
         }
170 258
 
171 259
         uint32_t now = to_ms_since_boot(get_absolute_time());
172
-        if ((now - start_time) >= CONNECT_TIMEOUT) {
260
+        if ((now - start_connect_time) >= CONNECT_TIMEOUT_MS) {
173 261
             debug("net connection timeout. retry.");
174 262
             wifi_scan();
175 263
         }
@@ -184,9 +272,8 @@ void wifi_run(void) {
184 272
         }
185 273
 
186 274
         uint32_t now = to_ms_since_boot(get_absolute_time());
187
-        if ((now - start_time) >= CONNECT_TIMEOUT) {
275
+        if ((now - start_ip_time) >= CONNECT_TIMEOUT_MS) {
188 276
             debug("net dhcp timeout. retry.");
189
-            start_time = now;
190 277
 
191 278
             //cyw43_arch_lwip_begin();
192 279
             //dhcp_renew(netif_default);

Loading…
Cancel
Save