1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include "private-lib-core.h"
26
27 #include "romfs.h"
28 #include <esp_ota_ops.h>
29 #include <tcpip_adapter.h>
30 #include <esp_image_format.h>
31 #include <esp_task_wdt.h>
32 #include "soc/ledc_reg.h"
33 #include "driver/ledc.h"
34
35 struct lws_esp32 lws_esp32 = {
36 .model = CONFIG_LWS_MODEL_NAME,
37 .serial = "unknown",
38 };
39
40 /*
41 * Group AP / Station State
42 */
43
44 enum lws_gapss {
45 LWS_GAPSS_INITIAL, /* just started up, init and move to
46 * LWS_GAPSS_SCAN */
47 LWS_GAPSS_SCAN, /*
48 * Unconnected, scanning: AP known in one of the
49 * config slots -> configure it, start timeout +
50 * LWS_GAPSS_STAT, if no AP already up in same
51 * group with lower MAC, after a random period
52 * start up our AP (LWS_GAPSS_AP)
53 */
54 LWS_GAPSS_AP, /*
55 * Trying to be the group AP... periodically do
56 * a scan LWS_GAPSS_AP_SCAN, faster and then
57 * slower
58 */
59 LWS_GAPSS_AP_SCAN, /*
60 * doing a scan while trying to be the group
61 * AP... if we see a lower MAC being the AP for
62 * the same group AP, abandon being an AP and
63 * join that AP as a station
64 */
65 LWS_GAPSS_STAT_GRP_AP, /*
66 * We have decided to join another group member
67 * who is being the AP, as its MAC is lower than
68 * ours. This is a stable state, but we still
69 * do periodic scans LWS_GAPSS_STAT_GRP_AP_SCAN
70 * and will always prefer an AP configured in a
71 * slot.
72 */
73 LWS_GAPSS_STAT_GRP_AP_SCAN,
74 /*
75 * We have joined a group member who is doing
76 * the AP job... we want to check every now and
77 * then if a configured AP has appeared that we
78 * should better use instead. Otherwise stay in
79 * LWS_GAPSS_STAT_GRP_AP
80 */
81 LWS_GAPSS_STAT, /*
82 * trying to connect to another non-group AP.
83 * If we don't get an IP within a timeout and
84 * retries, blacklist it and go back
85 */
86 LWS_GAPSS_STAT_HAPPY,
87 };
88
89 static const char *gapss_str[] = {
90 "LWS_GAPSS_INITIAL",
91 "LWS_GAPSS_SCAN",
92 "LWS_GAPSS_AP",
93 "LWS_GAPSS_AP_SCAN",
94 "LWS_GAPSS_STAT_GRP_AP",
95 "LWS_GAPSS_STAT_GRP_AP_SCAN",
96 "LWS_GAPSS_STAT",
97 "LWS_GAPSS_STAT_HAPPY",
98 };
99
100 static romfs_t lws_esp32_romfs;
101 static TimerHandle_t leds_timer, scan_timer, debounce_timer, association_timer
102 #if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION)
103 , mdns_timer
104 #endif
105 ;
106 static enum lws_gapss gapss = LWS_GAPSS_INITIAL;
107 #if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION)
108 static mdns_result_t *mdns_results_head;
109 #endif
110
111 #define GPIO_SW 14
112
113 struct esp32_file {
114 const struct inode *i;
115 };
116
lws_gapss_to(enum lws_gapss to)117 static void lws_gapss_to(enum lws_gapss to)
118 {
119 lwsl_notice("gapss from %s to %s\n", gapss_str[gapss], gapss_str[to]);
120 gapss = to;
121 }
122
lws_esp32_get_reboot_type(void)123 uint32_t lws_esp32_get_reboot_type(void)
124 {
125 uint32_t *p = (uint32_t *)LWS_MAGIC_REBOOT_TYPE_ADS, val = *p;
126 nvs_handle nvh;
127 size_t s = 0;
128 int n = 0;
129
130 ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh));
131 if (nvs_get_blob(nvh, "ssl-pub.pem", NULL, &s) == ESP_OK)
132 n = 1;
133 if (nvs_get_blob(nvh, "ssl-pri.pem", NULL, &s) == ESP_OK)
134 n |= 2;
135 nvs_close(nvh);
136
137 /*
138 * in the case the SSL certs are not there, don't require
139 * the button to be down to access all features.
140 */
141 if (n != 3)
142 val = LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON;
143
144 return val;
145 }
146
render_ip(char * dest,int len,uint8_t * ip)147 static void render_ip(char *dest, int len, uint8_t *ip)
148 {
149 snprintf(dest, len, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
150 }
151
lws_esp32_restart_guided(uint32_t type)152 void lws_esp32_restart_guided(uint32_t type)
153 {
154 uint32_t *p_force_factory_magic = (uint32_t *)LWS_MAGIC_REBOOT_TYPE_ADS;
155
156 lwsl_notice("%s: %x\n", __func__, type);
157 *p_force_factory_magic = type;
158
159 esp_restart();
160 }
161
162 /*
163 * esp-idf goes crazy with zero length str nvs. Use this as a workaround
164 * to delete the key in that case.
165 */
166
lws_nvs_set_str(nvs_handle handle,const char * key,const char * value)167 esp_err_t lws_nvs_set_str(nvs_handle handle, const char* key, const char* value)
168 {
169 if (*value)
170 return nvs_set_str(handle, key, value);
171
172 return nvs_erase_key(handle, key);
173 }
174
175 static wifi_scan_config_t scan_config = {
176 .ssid = 0,
177 .bssid = 0,
178 .channel = 0,
179 .show_hidden = true
180 };
181
182 static char scan_ongoing = 0, scan_timer_exists = 0;
183 static int try_slot = -1;
184
185 static wifi_config_t config = {
186 .ap = {
187 .channel = 6,
188 .authmode = WIFI_AUTH_OPEN,
189 .max_connection = 1,
190 } }, sta_config = {
191 .sta = {
192 .bssid_set = 0,
193 } };
194
lws_esp32_scan_timer_cb(TimerHandle_t th)195 static void lws_esp32_scan_timer_cb(TimerHandle_t th)
196 {
197 int n;
198
199 lwsl_notice("%s\n", __func__);
200 scan_ongoing = 0;
201 n = esp_wifi_scan_start(&scan_config, false);
202 if (n != ESP_OK)
203 lwsl_err("scan start failed %d\n", n);
204 }
205
lws_esp32_assoc_timer_cb(TimerHandle_t th)206 static void lws_esp32_assoc_timer_cb(TimerHandle_t th)
207 {
208 int n;
209
210 xTimerStop(association_timer, 0);
211
212 if (gapss == LWS_GAPSS_STAT_HAPPY) {
213 lwsl_debug("%s: saw we were happy\n", __func__);
214
215 return;
216 }
217
218 lwsl_notice("%s: forcing rescan\n", __func__);
219
220 lws_gapss_to(LWS_GAPSS_SCAN);
221 scan_ongoing = 0;
222 n = esp_wifi_scan_start(&scan_config, false);
223 if (n != ESP_OK)
224 lwsl_err("scan start failed %d\n", n);
225 }
226
227
228 #if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION)
229
230 void __attribute__(( weak ))
lws_group_member_event(int e,void * p)231 lws_group_member_event(int e, void *p)
232 {
233 }
234
235 void __attribute__(( weak ))
lws_get_iframe_size(int * w,int * h)236 lws_get_iframe_size(int *w, int *h)
237 {
238 *w = 320;
239 *h = 160;
240 }
241
lws_group_member_event_call(int e,void * p)242 void lws_group_member_event_call(int e, void *p)
243 {
244 lws_group_member_event(e, p);
245 }
246
247 static int
get_txt_param(const mdns_result_t * mr,const char * param,char * result,int len)248 get_txt_param(const mdns_result_t *mr, const char *param, char *result, int len)
249 {
250 const char *p;
251
252 *result = '\0';
253
254 p = strstr(mr->txt->key, param);
255 if (!p) {
256 *result = '\0';
257 return 1;
258 }
259
260 lws_strncpy(result, mr->txt->value, len);
261
262 return 0;
263 }
264
lws_esp32_mdns_timer_cb(TimerHandle_t th)265 static void lws_esp32_mdns_timer_cb(TimerHandle_t th)
266 {
267 uint64_t now = lws_now_usecs();
268 struct lws_group_member *p, **p1;
269 const mdns_result_t *r = mdns_results_head;
270
271 while (r) {
272 char ch = 0, group[16];
273
274 get_txt_param(r, "group", group, sizeof(group));
275 if (strcmp(group, lws_esp32.group)) /* not our group */ {
276 lwsl_notice("group %s vs %s %s\n",
277 group, lws_esp32.group, r->txt->value);
278 continue;
279 }
280
281 p = lws_esp32.first;
282 while (p) {
283 if (strcmp(r->hostname, p->host))
284 goto next;
285 if (memcmp(&r->addr, &p->addr, sizeof(r->addr)))
286 goto next;
287
288 p->last_seen = now;
289 break;
290 next:
291 p = p->next;
292 }
293 if (!p) { /* did not find */
294 char temp[8];
295
296 p = lws_malloc(sizeof(*p), "group");
297 if (!p)
298 continue;
299 lws_strncpy(p->host, r->hostname, sizeof(p->host));
300
301 get_txt_param(r, "model", p->model, sizeof(p->model));
302 get_txt_param(r, "role", p->role, sizeof(p->role));
303 get_txt_param(r, "mac", p->mac, sizeof(p->mac));
304 get_txt_param(r, "width", temp, sizeof(temp));
305 p->width = atoi(temp);
306 get_txt_param(r, "height", temp, sizeof(temp));
307 p->height = atoi(temp);
308
309 memcpy(&p->addr, &r->addr, sizeof(p->addr));
310 // memcpy(&p->addrv6, &r->addrv6, sizeof(p->addrv6));
311 p->last_seen = now;
312 p->flags = 0;
313 p->next = lws_esp32.first;
314 lws_esp32.first = p;
315 lws_esp32.extant_group_members++;
316
317 lws_group_member_event_call(LWS_SYSTEM_GROUP_MEMBER_ADD, p);
318 } else {
319 if (memcmp(&p->addr, &r->addr, sizeof(p->addr))) {
320 memcpy(&p->addr, &r->addr, sizeof(p->addr));
321 ch = 1;
322 }
323 /* if (memcmp(&p->addrv6, &r->addrv6, sizeof(p->addrv6))) {
324 memcpy(&p->addrv6, &r->addrv6, sizeof(p->addrv6));
325 ch = 1;
326 } */
327 if (ch)
328 lws_group_member_event_call(LWS_SYSTEM_GROUP_MEMBER_CHANGE, p);
329 }
330 }
331
332 mdns_query_results_free(mdns_results_head);
333
334 /* garbage-collect group members not seen for too long */
335 p1 = &lws_esp32.first;
336 while (*p1) {
337 p = *p1;
338 if (!(p->flags & LWS_GROUP_FLAG_SELF) &&
339 now - p->last_seen > 60000000) {
340 lws_esp32.extant_group_members--;
341 *p1 = p->next;
342
343 lws_group_member_event_call(LWS_SYSTEM_GROUP_MEMBER_REMOVE, p);
344 lws_free(p);
345 continue;
346 }
347 p1 = &(*p1)->next;
348 }
349
350 mdns_query_txt(lws_esp32.group, "_lwsgrmem", "_tcp", 0,
351 &mdns_results_head);
352 xTimerStart(mdns_timer, 0);
353 }
354 #endif
355
356 void __attribute__(( weak ))
lws_esp32_button(int down)357 lws_esp32_button(int down)
358 {
359 }
360
361 void IRAM_ATTR
gpio_irq(void * arg)362 gpio_irq(void *arg)
363 {
364 gpio_set_intr_type(GPIO_SW, GPIO_INTR_DISABLE);
365 xTimerStart(debounce_timer, 0);
366 }
367
lws_esp32_debounce_timer_cb(TimerHandle_t th)368 static void lws_esp32_debounce_timer_cb(TimerHandle_t th)
369 {
370 if (lws_esp32.button_is_down)
371 gpio_set_intr_type(GPIO_SW, GPIO_INTR_POSEDGE);
372 else
373 gpio_set_intr_type(GPIO_SW, GPIO_INTR_NEGEDGE);
374
375 lws_esp32.button_is_down = gpio_get_level(GPIO_SW);
376
377 lws_esp32_button(lws_esp32.button_is_down);
378 }
379
380
381 static int
start_scan()382 start_scan()
383 {
384 /* if no APs configured, no point... */
385
386 if (!lws_esp32.ssid[0][0] &&
387 !lws_esp32.ssid[1][0] &&
388 !lws_esp32.ssid[2][0] &&
389 !lws_esp32.ssid[3][0])
390 return 0;
391
392 if (scan_timer_exists && !scan_ongoing) {
393 // lwsl_notice("Starting scan timer...\n");
394 scan_ongoing = 1;
395 xTimerStart(scan_timer, 0);
396 }
397
398 return 0;
399 }
400
401
402
403 static void
end_scan()404 end_scan()
405 {
406 wifi_ap_record_t ap_records[10];
407 uint16_t count_ap_records;
408 int n, m;
409
410 count_ap_records = LWS_ARRAY_SIZE(ap_records);
411 if (esp_wifi_scan_get_ap_records(&count_ap_records, ap_records)) {
412 lwsl_err("%s: failed\n", __func__);
413 return;
414 }
415
416 if (!count_ap_records)
417 goto passthru;
418
419 if (gapss != LWS_GAPSS_SCAN) {
420 lwsl_info("ignoring scan as gapss %s\n", gapss_str[gapss]);
421 goto passthru;
422 }
423
424 /* no point if no APs set up */
425 if (!lws_esp32.ssid[0][0] &&
426 !lws_esp32.ssid[1][0] &&
427 !lws_esp32.ssid[2][0] &&
428 !lws_esp32.ssid[3][0])
429 goto passthru;
430
431 lwsl_info("checking %d scan records\n", count_ap_records);
432
433 for (n = 0; n < 4; n++) {
434
435 if (!lws_esp32.ssid[(n + try_slot + 1) & 3][0])
436 continue;
437
438 lwsl_debug("looking for %s\n",
439 lws_esp32.ssid[(n + try_slot + 1) & 3]);
440
441 /* this ssid appears in scan results? */
442
443 for (m = 0; m < count_ap_records; m++) {
444 // lwsl_notice(" %s\n", ap_records[m].ssid);
445 if (!strcmp((char *)ap_records[m].ssid,
446 lws_esp32.ssid[(n + try_slot + 1) & 3]))
447 goto hit;
448 }
449
450 continue;
451
452 hit:
453 m = (n + try_slot + 1) & 3;
454 try_slot = m;
455 lwsl_info("Attempting connection with slot %d: %s:\n", m,
456 lws_esp32.ssid[m]);
457 /* set the ssid we last tried to connect to */
458 lws_strncpy(lws_esp32.active_ssid, lws_esp32.ssid[m],
459 sizeof(lws_esp32.active_ssid));
460
461 lws_strncpy((char *)sta_config.sta.ssid, lws_esp32.ssid[m],
462 sizeof(sta_config.sta.ssid));
463 lws_strncpy((char *)sta_config.sta.password, lws_esp32.password[m],
464 sizeof(sta_config.sta.password));
465
466 tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA,
467 (const char *)&config.ap.ssid[7]);
468 lws_gapss_to(LWS_GAPSS_STAT);
469 xTimerStop(association_timer, 0);
470 xTimerStart(association_timer, 0);
471
472 esp_wifi_set_config(WIFI_IF_STA, &sta_config);
473 esp_wifi_connect();
474 break;
475 }
476
477 if (n == 4)
478 start_scan();
479
480 passthru:
481 if (lws_esp32.scan_consumer)
482 lws_esp32.scan_consumer(count_ap_records, ap_records,
483 lws_esp32.scan_consumer_arg);
484
485 }
486
487 static void
lws_set_genled(int n)488 lws_set_genled(int n)
489 {
490 lws_esp32.genled_t = lws_now_usecs();
491 lws_esp32.genled = n;
492 }
493
494 int
lws_esp32_leds_network_indication(void)495 lws_esp32_leds_network_indication(void)
496 {
497 uint64_t us, r;
498 int n, fadein = 100, speed = 1199, div = 1, base = 0;
499
500 r = lws_now_usecs();
501 us = r - lws_esp32.genled_t;
502
503 switch (lws_esp32.genled) {
504 case LWSESP32_GENLED__INIT:
505 lws_esp32.genled = LWSESP32_GENLED__LOST_NETWORK;
506 /* fallthru */
507 case LWSESP32_GENLED__LOST_NETWORK:
508 fadein = us / 10000; /* 100 steps in 1s */
509 if (fadein > 100) {
510 fadein = 100;
511 lws_esp32.genled = LWSESP32_GENLED__NO_NETWORK;
512 }
513 /* fallthru */
514 case LWSESP32_GENLED__NO_NETWORK:
515 break;
516 case LWSESP32_GENLED__CONN_AP:
517 base = 4096;
518 speed = 933;
519 div = 2;
520 break;
521 case LWSESP32_GENLED__GOT_IP:
522 fadein = us / 10000; /* 100 steps in 1s */
523 if (fadein > 100) {
524 fadein = 100;
525 lws_esp32.genled = LWSESP32_GENLED__OK;
526 }
527 fadein = 100 - fadein; /* we are fading out */
528 /* fallthru */
529 case LWSESP32_GENLED__OK:
530 if (lws_esp32.genled == LWSESP32_GENLED__OK)
531 return 0;
532
533 base = 4096;
534 speed = 766;
535 div = 3;
536 break;
537 }
538
539 n = base + (lws_esp32_sine_interp(r / speed) / div);
540 return (n * fadein) / 100;
541 }
542
lws_esp32_event_passthru(void * ctx,system_event_t * event)543 esp_err_t lws_esp32_event_passthru(void *ctx, system_event_t *event)
544 {
545 #if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION)
546 struct lws_group_member *mem;
547 int n;
548 #endif
549 nvs_handle nvh;
550 uint32_t use;
551
552 switch((int)event->event_id) {
553 case SYSTEM_EVENT_STA_START:
554 //esp_wifi_connect();
555 // break;
556 /* fallthru */
557 case SYSTEM_EVENT_STA_DISCONNECTED:
558 lwsl_notice("SYSTEM_EVENT_STA_DISCONNECTED\n");
559 if (sntp_enabled())
560 sntp_stop();
561 lws_esp32.conn_ap = 0;
562 lws_esp32.inet = 0;
563 lws_esp32.sta_ip[0] = '\0';
564 lws_esp32.sta_mask[0] = '\0';
565 lws_esp32.sta_gw[0] = '\0';
566 lws_gapss_to(LWS_GAPSS_SCAN);
567 mdns_free();
568 lws_set_genled(LWSESP32_GENLED__LOST_NETWORK);
569 start_scan();
570 esp_wifi_connect();
571 break;
572
573 case SYSTEM_EVENT_STA_CONNECTED:
574 lws_esp32.conn_ap = 1;
575 lws_set_genled(LWSESP32_GENLED__CONN_AP);
576 break;
577
578 case SYSTEM_EVENT_STA_GOT_IP:
579 lwsl_notice("SYSTEM_EVENT_STA_GOT_IP\n");
580
581 lws_esp32.inet = 1;
582 lws_set_genled(LWSESP32_GENLED__GOT_IP);
583
584 render_ip(lws_esp32.sta_ip, sizeof(lws_esp32.sta_ip) - 1,
585 (uint8_t *)&event->event_info.got_ip.ip_info.ip);
586 render_ip(lws_esp32.sta_mask, sizeof(lws_esp32.sta_mask) - 1,
587 (uint8_t *)&event->event_info.got_ip.ip_info.netmask);
588 render_ip(lws_esp32.sta_gw, sizeof(lws_esp32.sta_gw) - 1,
589 (uint8_t *)&event->event_info.got_ip.ip_info.gw);
590
591 if (!nvs_open("lws-station", NVS_READWRITE, &nvh)) {
592 char slot[8];
593
594 lws_snprintf(slot, sizeof(slot) - 1, "%duse", try_slot);
595 use = 0;
596 nvs_get_u32(nvh, slot, &use);
597 nvs_set_u32(nvh, slot, use + 1);
598 nvs_commit(nvh);
599 nvs_close(nvh);
600 }
601
602 lws_gapss_to(LWS_GAPSS_STAT_HAPPY);
603
604 #if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION)
605 n = mdns_init();
606 if (!n) {
607 static mdns_txt_item_t txta[6];
608 static char wh[2][6];
609 int w, h;
610
611 mdns_hostname_set(lws_esp32.hostname);
612 mdns_instance_name_set(lws_esp32.group);
613
614 lws_get_iframe_size(&w, &h);
615
616 txta[0].key = "model";
617 txta[1].key = "group";
618 txta[2].key = "role";
619 txta[3].key = "mac";
620 txta[4].key = "width";
621 txta[5].key = "height";
622
623 txta[0].value = lws_esp32.model;
624 txta[1].value = lws_esp32.group;
625 txta[2].value = lws_esp32.role;
626 txta[3].value = lws_esp32.mac;
627 txta[4].value = wh[0];
628 txta[5].value = wh[1];
629
630 lws_snprintf(wh[0], 6, "%d", w);
631 lws_snprintf(wh[1], 6, "%d", h);
632
633 mdns_service_add(lws_esp32.group,
634 "_lwsgrmem", "_tcp", 443, txta,
635 LWS_ARRAY_SIZE(txta));
636
637 mem = lws_esp32.first;
638 while (mem) {
639 if (mem->flags & 1)
640 break;
641 mem = mem->next;
642 }
643
644 if (!mem) {
645 struct lws_group_member *mem =
646 lws_malloc(sizeof(*mem), "group");
647 if (mem) {
648 mem->last_seen = ~(uint64_t)0;
649 strcpy(mem->model, lws_esp32.model);
650 strcpy(mem->role, lws_esp32.role);
651 strcpy(mem->host, lws_esp32.hostname);
652 strcpy(mem->mac, lws_esp32.mac);
653 mem->flags = LWS_GROUP_FLAG_SELF;
654 lws_get_iframe_size(&mem->width,
655 &mem->height);
656 memcpy(&mem->addr,
657 &event->event_info.got_ip.ip_info.ip,
658 sizeof(mem->addr));
659 memcpy(&mem->addrv6,
660 &event->event_info.got_ip6.ip6_info.ip,
661 sizeof(mem->addrv6));
662 mem->next = lws_esp32.first;
663 lws_esp32.first = mem;
664 lws_esp32.extant_group_members++;
665
666 lws_group_member_event_call(
667 LWS_SYSTEM_GROUP_MEMBER_ADD, mem);
668 }
669 } else { /* update our IP */
670 memcpy(&mem->addr,
671 &event->event_info.got_ip.ip_info.ip,
672 sizeof(mem->addr));
673 memcpy(&mem->addrv6,
674 &event->event_info.got_ip6.ip6_info.ip,
675 sizeof(mem->addrv6));
676 lws_group_member_event_call(
677 LWS_SYSTEM_GROUP_MEMBER_CHANGE, mem);
678 }
679
680 } else
681 lwsl_err("unable to init mdns on STA: %d\n", n);
682
683 mdns_query_txt(lws_esp32.group, "_lwsgrmem", "_tcp", 0,
684 &mdns_results_head);
685 xTimerStart(mdns_timer, 0);
686 #endif
687
688 lwsl_notice(" --- Got IP %s\n", lws_esp32.sta_ip);
689 if (!sntp_enabled()) {
690 sntp_setoperatingmode(SNTP_OPMODE_POLL);
691 sntp_setservername(0, "pool.ntp.org");
692 sntp_init();
693 }
694 break;
695
696 case SYSTEM_EVENT_SCAN_DONE:
697 lwsl_notice("SYSTEM_EVENT_SCAN_DONE\n");
698 end_scan();
699 break;
700
701 default:
702 break;
703 }
704
705 return ESP_OK;
706 }
707
708 #if defined(LWS_WITH_FILE_OPS)
709 static lws_fop_fd_t IRAM_ATTR
esp32_lws_fops_open(const struct lws_plat_file_ops * fops,const char * filename,const char * vfs_path,lws_fop_flags_t * flags)710 esp32_lws_fops_open(const struct lws_plat_file_ops *fops, const char *filename,
711 const char *vfs_path, lws_fop_flags_t *flags)
712 {
713 struct esp32_file *f = malloc(sizeof(*f));
714 lws_fop_fd_t fop_fd;
715 size_t len, csum;
716
717 lwsl_notice("%s: %s\n", __func__, filename);
718
719 if (!f)
720 return NULL;
721 f->i = romfs_get_info(lws_esp32_romfs, filename, &len, &csum);
722 if (!f->i)
723 goto bail;
724
725 fop_fd = malloc(sizeof(*fop_fd));
726 if (!fop_fd)
727 goto bail;
728
729 fop_fd->fops = fops;
730 fop_fd->filesystem_priv = f;
731 fop_fd->mod_time = csum;
732 *flags |= LWS_FOP_FLAG_MOD_TIME_VALID;
733 fop_fd->flags = *flags;
734
735 fop_fd->len = len;
736 fop_fd->pos = 0;
737
738 return fop_fd;
739
740 bail:
741 free(f);
742
743 return NULL;
744 }
745
746 static int IRAM_ATTR
esp32_lws_fops_close(lws_fop_fd_t * fop_fd)747 esp32_lws_fops_close(lws_fop_fd_t *fop_fd)
748 {
749 free((*fop_fd)->filesystem_priv);
750 free(*fop_fd);
751
752 *fop_fd = NULL;
753
754 return 0;
755 }
756 static lws_fileofs_t IRAM_ATTR
esp32_lws_fops_seek_cur(lws_fop_fd_t fop_fd,lws_fileofs_t offset_from_cur_pos)757 esp32_lws_fops_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset_from_cur_pos)
758 {
759 fop_fd->pos += offset_from_cur_pos;
760
761 if (fop_fd->pos > fop_fd->len)
762 fop_fd->pos = fop_fd->len;
763
764 return 0;
765 }
766
767 static int IRAM_ATTR
esp32_lws_fops_read(lws_fop_fd_t fop_fd,lws_filepos_t * amount,uint8_t * buf,lws_filepos_t len)768 esp32_lws_fops_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount, uint8_t *buf,
769 lws_filepos_t len)
770 {
771 struct esp32_file *f = fop_fd->filesystem_priv;
772 #if 0
773 if ((long)buf & 3) {
774 lwsl_err("misaligned buf\n");
775
776 return -1;
777 }
778 #endif
779 if (fop_fd->pos >= fop_fd->len)
780 return 0;
781
782 if (len > fop_fd->len - fop_fd->pos)
783 len = fop_fd->len - fop_fd->pos;
784
785 spi_flash_read((uint32_t)(char *)f->i + fop_fd->pos, buf, len);
786
787 *amount = len;
788 fop_fd->pos += len;
789
790 return 0;
791 }
792
793 static const struct lws_plat_file_ops fops = {
794 .next = &fops_zip,
795 .LWS_FOP_OPEN = esp32_lws_fops_open,
796 .LWS_FOP_CLOSE = esp32_lws_fops_close,
797 .LWS_FOP_READ = esp32_lws_fops_read,
798 .LWS_FOP_SEEK_CUR = esp32_lws_fops_seek_cur,
799 };
800 #endif
801
802 int
lws_esp32_wlan_nvs_get(int retry)803 lws_esp32_wlan_nvs_get(int retry)
804 {
805 nvs_handle nvh;
806 char lws_esp32_force_ap = 0, slot[12];
807 size_t s;
808 uint8_t mac[6];
809 int n;
810
811 esp_efuse_mac_get_default(mac);
812 mac[5] |= 1; /* match the AP MAC */
813 snprintf(lws_esp32.serial, sizeof(lws_esp32.serial) - 1,
814 "%02X%02X%02X", mac[3], mac[4], mac[5]);
815 snprintf(lws_esp32.mac, sizeof(lws_esp32.mac) - 1,
816 "%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3],
817 mac[4], mac[5]);
818
819 ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh));
820
821 config.sta.ssid[0] = '\0';
822 config.sta.password[0] = '\0';
823
824 for (n = 0; n < 4; n++) {
825 lws_snprintf(slot, sizeof(slot) - 1, "%dssid", n);
826 s = sizeof(lws_esp32.ssid[0]) - 1;
827 lws_esp32.ssid[n][0] = '\0';
828 nvs_get_str(nvh, slot, lws_esp32.ssid[n], &s);
829
830 lws_snprintf(slot, sizeof(slot) - 1, "%dpassword", n);
831 s = sizeof(lws_esp32.password[0]) - 1;
832 lws_esp32.password[n][0] = '\0';
833 nvs_get_str(nvh, slot, lws_esp32.password[n], &s);
834 }
835
836 s = sizeof(lws_esp32.serial) - 1;
837 if (nvs_get_str(nvh, "serial", lws_esp32.serial, &s) != ESP_OK)
838 lws_esp32_force_ap = 1;
839 else
840 snprintf((char *)config.ap.ssid, sizeof(config.ap.ssid) - 1,
841 "config-%s-%s", lws_esp32.model, lws_esp32.serial);
842 s = sizeof(lws_esp32.opts) - 1;
843 if (nvs_get_str(nvh, "opts", lws_esp32.opts, &s) != ESP_OK)
844 lws_esp32_force_ap = 1;
845
846 lws_esp32.access_pw[0] = '\0';
847 nvs_get_str(nvh, "access_pw", lws_esp32.access_pw, &s);
848
849 lws_esp32.group[0] = '\0';
850 s = sizeof(lws_esp32.group);
851 nvs_get_str(nvh, "group", lws_esp32.group, &s);
852
853 lws_esp32.role[0] = '\0';
854 s = sizeof(lws_esp32.role);
855 nvs_get_str(nvh, "role", lws_esp32.role, &s);
856
857 /* if group and role defined: group-role */
858 if (lws_esp32.group[0] && lws_esp32.role[0])
859 lws_snprintf(lws_esp32.hostname, sizeof(lws_esp32.hostname) - 1,
860 "%s-%s", lws_esp32.group, lws_esp32.role);
861 else /* otherwise model-serial */
862 lws_snprintf(lws_esp32.hostname, sizeof(lws_esp32.hostname) - 1,
863 "%s-%s", lws_esp32.model, lws_esp32.serial);
864
865 nvs_close(nvh);
866
867 lws_gapss_to(LWS_GAPSS_SCAN);
868 start_scan();
869
870 return lws_esp32_force_ap;
871 }
872
873
874 void
lws_esp32_wlan_config(void)875 lws_esp32_wlan_config(void)
876 {
877 ledc_timer_config_t ledc_timer = {
878 .bit_num = LEDC_TIMER_13_BIT,
879 .freq_hz = 5000,
880 .speed_mode = LEDC_HIGH_SPEED_MODE,
881 .timer_num = LEDC_TIMER_0
882 };
883 int n;
884
885 lwsl_debug("%s\n", __func__);
886
887 ledc_timer_config(&ledc_timer);
888
889 lws_set_genled(LWSESP32_GENLED__INIT);
890
891 /* user code needs to provide lws_esp32_leds_timer_cb */
892
893 leds_timer = xTimerCreate("lws_leds", pdMS_TO_TICKS(25), 1, NULL,
894 (TimerCallbackFunction_t)lws_esp32_leds_timer_cb);
895 scan_timer = xTimerCreate("lws_scan", pdMS_TO_TICKS(10000), 0, NULL,
896 (TimerCallbackFunction_t)lws_esp32_scan_timer_cb);
897 debounce_timer = xTimerCreate("lws_db", pdMS_TO_TICKS(100), 0, NULL,
898 (TimerCallbackFunction_t)lws_esp32_debounce_timer_cb);
899 association_timer = xTimerCreate("lws_assoc", pdMS_TO_TICKS(10000), 0, NULL,
900 (TimerCallbackFunction_t)lws_esp32_assoc_timer_cb);
901
902 #if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION)
903 mdns_timer = xTimerCreate("lws_mdns", pdMS_TO_TICKS(5000), 0, NULL,
904 (TimerCallbackFunction_t)lws_esp32_mdns_timer_cb);
905 #endif
906 scan_timer_exists = 1;
907 xTimerStart(leds_timer, 0);
908
909 *(volatile uint32_t *)PERIPHS_IO_MUX_MTMS_U = FUNC_MTMS_GPIO14;
910
911 gpio_output_set(0, 0, 0, (1 << GPIO_SW));
912
913 n = gpio_install_isr_service(0);
914 if (!n) {
915 gpio_config_t c;
916
917 c.intr_type = GPIO_INTR_NEGEDGE;
918 c.mode = GPIO_MODE_INPUT;
919 c.pin_bit_mask = 1 << GPIO_SW;
920 c.pull_down_en = 0;
921 c.pull_up_en = 0;
922 gpio_config(&c);
923
924 if (gpio_isr_handler_add(GPIO_SW, gpio_irq, NULL))
925 lwsl_notice("isr handler add for 14 failed\n");
926 } else
927 lwsl_notice("failed to install gpio isr service: %d\n", n);
928
929 lws_esp32_wlan_nvs_get(0);
930 tcpip_adapter_init();
931 }
932
933 void
lws_esp32_wlan_start_ap(void)934 lws_esp32_wlan_start_ap(void)
935 {
936 wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
937
938 ESP_ERROR_CHECK( esp_wifi_init(&cfg));
939 ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM));
940
941 ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_APSTA) );
942 ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_AP, &config) );
943 ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config));
944 ESP_ERROR_CHECK( esp_wifi_start());
945
946 esp_wifi_scan_start(&scan_config, false);
947
948 if (sta_config.sta.ssid[0]) {
949 tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA,
950 (const char *)&config.ap.ssid[7]);
951 // esp_wifi_set_auto_connect(1);
952 ESP_ERROR_CHECK( esp_wifi_connect());
953 ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config));
954 ESP_ERROR_CHECK( esp_wifi_connect());
955 }
956 }
957
958 void
lws_esp32_wlan_start_station(void)959 lws_esp32_wlan_start_station(void)
960 {
961 wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
962
963 ESP_ERROR_CHECK( esp_wifi_init(&cfg));
964 ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM));
965
966 ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA));
967 ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config));
968
969 ESP_ERROR_CHECK( esp_wifi_start());
970
971 tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA,
972 (const char *)&config.ap.ssid[7]);
973 //esp_wifi_set_auto_connect(1);
974 //ESP_ERROR_CHECK( esp_wifi_connect());
975
976 lws_esp32_scan_timer_cb(NULL);
977 }
978
979 const esp_partition_t *
lws_esp_ota_get_boot_partition(void)980 lws_esp_ota_get_boot_partition(void)
981 {
982 const esp_partition_t *part = esp_ota_get_boot_partition(),
983 *factory_part, *ota;
984 esp_image_header_t eih, ota_eih;
985 uint32_t *p_force_factory_magic = (uint32_t *)LWS_MAGIC_REBOOT_TYPE_ADS;
986
987 /* confirm what we are told is the boot part is sane */
988 spi_flash_read(part->address , &eih, sizeof(eih));
989 factory_part = esp_partition_find_first(ESP_PARTITION_TYPE_APP,
990 ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
991 ota = esp_partition_find_first(ESP_PARTITION_TYPE_APP,
992 ESP_PARTITION_SUBTYPE_APP_OTA_0, NULL);
993 spi_flash_read(ota->address , &ota_eih, sizeof(ota_eih));
994
995 if (eih.spi_mode == 0xff ||
996 *p_force_factory_magic == LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY ||
997 *p_force_factory_magic == LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON
998 ) {
999 /*
1000 * we believed we were going to boot OTA, but we fell
1001 * back to FACTORY in the bootloader when we saw it
1002 * had been erased. esp_ota_get_boot_partition() still
1003 * says the OTA partition then even if we are in the
1004 * factory partition right now.
1005 */
1006 part = factory_part;
1007 }
1008
1009 #ifdef CONFIG_LWS_IS_FACTORY_APPLICATION
1010 else
1011 if (ota_eih.spi_mode != 0xff &&
1012 part->address != factory_part->address) {
1013 uint8_t buf[4096];
1014 uint32_t n;
1015 /*
1016 * we are a FACTORY image running in an OTA slot...
1017 * it means we were just written and need to copy
1018 * ourselves into the FACTORY slot.
1019 */
1020 lwsl_notice("Copying FACTORY update into place "
1021 "0x%x len 0x%x\n", factory_part->address,
1022 factory_part->size);
1023 esp_task_wdt_reset();
1024 if (spi_flash_erase_range(factory_part->address,
1025 factory_part->size)) {
1026 lwsl_err("spi: Failed to erase\n");
1027 goto retry;
1028 }
1029
1030 for (n = 0; n < factory_part->size; n += sizeof(buf)) {
1031 esp_task_wdt_reset();
1032 spi_flash_read(part->address + n , buf,
1033 sizeof(buf));
1034 if (spi_flash_write(factory_part->address + n,
1035 buf, sizeof(buf))) {
1036 lwsl_err("spi: Failed to write\n");
1037 goto retry;
1038 }
1039 }
1040
1041 /*
1042 * We send a message to the bootloader to erase the OTA header, we will come back up in
1043 * factory where the user can reload the OTA image
1044 */
1045 lwsl_notice(" FACTORY copy successful, rebooting\n");
1046 lws_esp32_restart_guided(LWS_MAGIC_REBOOT_TYPE_REQ_FACTORY_ERASE_OTA);
1047 retry:
1048 esp_restart();
1049 }
1050 #endif
1051
1052 return part;
1053 }
1054
1055
1056 void
lws_esp32_set_creation_defaults(struct lws_context_creation_info * info)1057 lws_esp32_set_creation_defaults(struct lws_context_creation_info *info)
1058 {
1059 const esp_partition_t *part;
1060
1061 memset(info, 0, sizeof(*info));
1062
1063 lws_set_log_level(63, lwsl_emit_syslog);
1064
1065 part = lws_esp_ota_get_boot_partition();
1066 (void)part;
1067
1068 info->vhost_name = "default";
1069 info->port = 443;
1070 info->fd_limit_per_thread = 16;
1071 info->max_http_header_pool = 5;
1072 info->max_http_header_data = 1024;
1073 info->pt_serv_buf_size = 4096;
1074 info->keepalive_timeout = 30;
1075 info->timeout_secs = 30;
1076 info->simultaneous_ssl_restriction = 2;
1077 info->options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS |
1078 LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
1079 }
1080
1081 int
lws_esp32_get_image_info(const esp_partition_t * part,struct lws_esp32_image * i,char * json,int json_len)1082 lws_esp32_get_image_info(const esp_partition_t *part, struct lws_esp32_image *i,
1083 char *json, int json_len)
1084 {
1085 esp_image_segment_header_t eis;
1086 esp_image_header_t eih;
1087 uint32_t hdr;
1088
1089 spi_flash_read(part->address , &eih, sizeof(eih));
1090 hdr = part->address + sizeof(eih);
1091
1092 if (eih.magic != ESP_IMAGE_HEADER_MAGIC) {
1093 lwsl_notice("%s: bad image header magic\n", __func__);
1094 return 1;
1095 }
1096
1097 eis.data_len = 0;
1098 while (eih.segment_count-- && eis.data_len != 0xffffffff) {
1099 spi_flash_read(hdr, &eis, sizeof(eis));
1100 hdr += sizeof(eis) + eis.data_len;
1101 }
1102 hdr += (~hdr & 15) + 1;
1103
1104 if (eih.hash_appended)
1105 hdr += 0x20;
1106
1107 // lwsl_notice("romfs estimated at 0x%x\n", hdr);
1108
1109 i->romfs = hdr + 0x4;
1110 spi_flash_read(hdr, &i->romfs_len, sizeof(i->romfs_len));
1111 i->json = i->romfs + i->romfs_len + 4;
1112 spi_flash_read(i->json - 4, &i->json_len, sizeof(i->json_len));
1113
1114 if (i->json_len < json_len - 1)
1115 json_len = i->json_len;
1116 spi_flash_read(i->json, json, json_len);
1117 json[json_len] = '\0';
1118
1119 return 0;
1120 }
1121
1122 static int
_rngf(void * context,unsigned char * buf,size_t len)1123 _rngf(void *context, unsigned char *buf, size_t len)
1124 {
1125 if (lws_get_random(context, buf, len) == len)
1126 return 0;
1127
1128 return -1;
1129 }
1130
1131 int
lws_esp32_selfsigned(struct lws_vhost * vhost)1132 lws_esp32_selfsigned(struct lws_vhost *vhost)
1133 {
1134 mbedtls_x509write_cert crt;
1135 char subject[200];
1136 mbedtls_pk_context mpk;
1137 int buf_size = 4096, n;
1138 uint8_t *buf = malloc(buf_size); /* malloc because given to user code */
1139 mbedtls_mpi mpi;
1140 nvs_handle nvh;
1141 size_t s;
1142
1143 lwsl_notice("%s: %s\n", __func__, vhost->name);
1144
1145 if (!buf)
1146 return -1;
1147
1148 if (nvs_open("lws-station", NVS_READWRITE, &nvh)) {
1149 lwsl_notice("%s: can't open nvs\n", __func__);
1150 free(buf);
1151 return 1;
1152 }
1153
1154 n = 0;
1155 if (!nvs_get_blob(nvh, vhost->tls.alloc_cert_path, NULL, &s))
1156 n |= 1;
1157 if (!nvs_get_blob(nvh, vhost->tls.key_path, NULL, &s))
1158 n |= 2;
1159
1160 nvs_close(nvh);
1161 if (n == 3) {
1162 lwsl_notice("%s: certs exist\n", __func__);
1163 free(buf);
1164 return 0; /* certs already exist */
1165 }
1166
1167 lwsl_notice("%s: creating selfsigned initial certs\n", __func__);
1168
1169 mbedtls_x509write_crt_init(&crt);
1170
1171 mbedtls_pk_init(&mpk);
1172 if (mbedtls_pk_setup(&mpk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA))) {
1173 lwsl_notice("%s: pk_setup failed\n", __func__);
1174 goto fail;
1175 }
1176 lwsl_notice("%s: generating 2048-bit RSA keypair... "
1177 "this may take a minute or so...\n", __func__);
1178 n = mbedtls_rsa_gen_key(mbedtls_pk_rsa(mpk), _rngf, vhost->context,
1179 2048, 65537);
1180 if (n) {
1181 lwsl_notice("%s: failed to generate keys\n", __func__);
1182 goto fail1;
1183 }
1184 lwsl_notice("%s: keys done\n", __func__);
1185
1186 /* subject must be formatted like "C=TW,O=warmcat,CN=myserver" */
1187
1188 lws_snprintf(subject, sizeof(subject) - 1,
1189 "C=TW,ST=New Taipei City,L=Taipei,O=warmcat,CN=%s",
1190 lws_esp32.hostname);
1191
1192 if (mbedtls_x509write_crt_set_subject_name(&crt, subject)) {
1193 lwsl_notice("set SN failed\n");
1194 goto fail1;
1195 }
1196 mbedtls_x509write_crt_set_subject_key(&crt, &mpk);
1197 if (mbedtls_x509write_crt_set_issuer_name(&crt, subject)) {
1198 lwsl_notice("set IN failed\n");
1199 goto fail1;
1200 }
1201 mbedtls_x509write_crt_set_issuer_key(&crt, &mpk);
1202
1203 lws_get_random(vhost->context, &n, sizeof(n));
1204 lws_snprintf(subject, sizeof(subject), "%d", n);
1205
1206 mbedtls_mpi_init(&mpi);
1207 mbedtls_mpi_read_string(&mpi, 10, subject);
1208 mbedtls_x509write_crt_set_serial(&crt, &mpi);
1209 mbedtls_mpi_free(&mpi);
1210
1211 mbedtls_x509write_crt_set_validity(&crt, "20171105235959",
1212 "20491231235959");
1213
1214 mbedtls_x509write_crt_set_key_usage(&crt,
1215 MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
1216 MBEDTLS_X509_KU_KEY_ENCIPHERMENT);
1217
1218
1219 mbedtls_x509write_crt_set_md_alg(&crt, MBEDTLS_MD_SHA256);
1220
1221 n = mbedtls_x509write_crt_pem(&crt, buf, buf_size, _rngf,
1222 vhost->context);
1223 if (n < 0) {
1224 lwsl_notice("%s: write crt der failed\n", __func__);
1225 goto fail1;
1226 }
1227
1228 lws_plat_write_cert(vhost, 0, 0, buf, strlen((const char *)buf));
1229
1230 if (mbedtls_pk_write_key_pem(&mpk, buf, buf_size)) {
1231 lwsl_notice("write key pem failed\n");
1232 goto fail1;
1233 }
1234
1235 lws_plat_write_cert(vhost, 1, 0, buf, strlen((const char *)buf));
1236
1237 mbedtls_pk_free(&mpk);
1238 mbedtls_x509write_crt_free(&crt);
1239
1240 lwsl_notice("%s: cert creation complete\n", __func__);
1241
1242 return n;
1243
1244 fail1:
1245 mbedtls_pk_free(&mpk);
1246 fail:
1247 mbedtls_x509write_crt_free(&crt);
1248 free(buf);
1249
1250 nvs_close(nvh);
1251
1252 return -1;
1253 }
1254
1255 void
lws_esp32_update_acme_info(void)1256 lws_esp32_update_acme_info(void)
1257 {
1258 int n;
1259
1260 n = lws_plat_read_file("acme-email", lws_esp32.le_email,
1261 sizeof(lws_esp32.le_email) - 1);
1262 if (n >= 0)
1263 lws_esp32.le_email[n] = '\0';
1264
1265 n = lws_plat_read_file("acme-cn", lws_esp32.le_dns,
1266 sizeof(lws_esp32.le_dns) - 1);
1267 if (n >= 0)
1268 lws_esp32.le_dns[n] = '\0';
1269 }
1270
1271 struct lws_context *
lws_esp32_init(struct lws_context_creation_info * info,struct lws_vhost ** pvh)1272 lws_esp32_init(struct lws_context_creation_info *info, struct lws_vhost **pvh)
1273 {
1274 const esp_partition_t *part = lws_esp_ota_get_boot_partition();
1275 struct lws_context *context;
1276 struct lws_esp32_image i;
1277 struct lws_vhost *vhost;
1278 struct lws wsi;
1279 char buf[512];
1280
1281 context = lws_create_context(info);
1282 if (context == NULL) {
1283 lwsl_err("Failed to create context\n");
1284 return NULL;
1285 }
1286
1287 lws_esp32_get_image_info(part, &i, buf, sizeof(buf) - 1);
1288
1289 lws_esp32_romfs = (romfs_t)i.romfs;
1290 if (!romfs_mount_check(lws_esp32_romfs)) {
1291 lwsl_err("mount error on ROMFS at %p 0x%x\n", lws_esp32_romfs,
1292 i.romfs);
1293 return NULL;
1294 }
1295
1296 lwsl_notice("ROMFS length %uKiB\n", i.romfs_len >> 10);
1297
1298 puts(buf);
1299
1300 /* set the lws vfs to use our romfs */
1301 #if defined(LWS_WITH_FILE_OPS)
1302 lws_set_fops(context, &fops);
1303 #endif
1304
1305 info->options |= LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX |
1306 LWS_SERVER_OPTION_IGNORE_MISSING_CERT;
1307
1308 vhost = lws_create_vhost(context, info);
1309 if (!vhost) {
1310 lwsl_err("Failed to create vhost\n");
1311 return NULL;
1312 }
1313
1314 lws_esp32_update_acme_info();
1315
1316 lws_esp32_selfsigned(vhost);
1317 wsi.context = vhost->context;
1318 wsi.vhost = vhost;
1319
1320 lws_tls_server_certs_load(vhost, &wsi, info->ssl_cert_filepath,
1321 info->ssl_private_key_filepath, NULL, 0, NULL, 0);
1322
1323 lws_init_vhost_client_ssl(info, vhost);
1324
1325 if (pvh)
1326 *pvh = vhost;
1327
1328 if (lws_protocol_init(context))
1329 return NULL;
1330
1331 return context;
1332 }
1333
1334 static const uint16_t sineq16[] = {
1335 0x0000, 0x0191, 0x031e, 0x04a4, 0x061e, 0x0789, 0x08e2, 0x0a24,
1336 0x0b4e, 0x0c5c, 0x0d4b, 0x0e1a, 0x0ec6, 0x0f4d, 0x0faf, 0x0fea,
1337 };
1338
sine_lu(int n)1339 static uint16_t sine_lu(int n)
1340 {
1341 switch ((n >> 4) & 3) {
1342 case 1:
1343 return 4096 + sineq16[n & 15];
1344 case 2:
1345 return 4096 + sineq16[15 - (n & 15)];
1346 case 3:
1347 return 4096 - sineq16[n & 15];
1348 default:
1349 return 4096 - sineq16[15 - (n & 15)];
1350 }
1351 }
1352
1353 /* useful for sine led fade patterns */
1354
lws_esp32_sine_interp(int n)1355 uint16_t lws_esp32_sine_interp(int n)
1356 {
1357 /*
1358 * 2: quadrant
1359 * 4: table entry in quadrant
1360 * 4: interp (LSB)
1361 *
1362 * total 10 bits / 1024 steps per cycle
1363 *
1364 * + 0: 0
1365 * + 256: 4096
1366 * + 512: 8192
1367 * + 768: 4096
1368 * +1023: 0
1369 */
1370
1371 return (sine_lu(n >> 4) * (15 - (n & 15)) +
1372 sine_lu((n >> 4) + 1) * (n & 15)) / 15;
1373 }
1374