lws-plat-esp32.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. #include "private-libwebsockets.h"
  2. #include "freertos/timers.h"
  3. #include <esp_attr.h>
  4. /*
  5. * included from libwebsockets.c for unix builds
  6. */
  7. unsigned long long time_in_microseconds(void)
  8. {
  9. struct timeval tv;
  10. gettimeofday(&tv, NULL);
  11. return ((unsigned long long)tv.tv_sec * 1000000LL) + tv.tv_usec;
  12. }
  13. LWS_VISIBLE int
  14. lws_get_random(struct lws_context *context, void *buf, int len)
  15. {
  16. // !!!
  17. return 0;
  18. }
  19. LWS_VISIBLE int
  20. lws_send_pipe_choked(struct lws *wsi)
  21. {
  22. fd_set writefds;
  23. struct timeval tv = { 0, 0 };
  24. /* treat the fact we got a truncated send pending as if we're choked */
  25. if (wsi->trunc_len)
  26. return 1;
  27. FD_ZERO(&writefds);
  28. FD_SET(wsi->desc.sockfd, &writefds);
  29. if (select(wsi->desc.sockfd + 1, NULL, &writefds, NULL, &tv) < 1)
  30. return 1;
  31. return 0;
  32. }
  33. LWS_VISIBLE int
  34. lws_poll_listen_fd(struct lws_pollfd *fd)
  35. {
  36. fd_set readfds;
  37. struct timeval tv = { 0, 0 };
  38. FD_ZERO(&readfds);
  39. FD_SET(fd->fd, &readfds);
  40. return select(fd->fd + 1, &readfds, NULL, NULL, &tv);
  41. }
  42. LWS_VISIBLE void
  43. lws_cancel_service_pt(struct lws *wsi)
  44. {
  45. }
  46. LWS_VISIBLE void
  47. lws_cancel_service(struct lws_context *context)
  48. {
  49. }
  50. LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line)
  51. {
  52. printf("%d: %s", level, line);
  53. }
  54. LWS_VISIBLE LWS_EXTERN int
  55. _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
  56. {
  57. struct lws_context_per_thread *pt;
  58. int n = -1, m, c;
  59. /* stay dead once we are dead */
  60. if (!context || !context->vhost_list)
  61. return 1;
  62. pt = &context->pt[tsi];
  63. if (timeout_ms < 0)
  64. goto faked_service;
  65. if (!context->service_tid_detected) {
  66. struct lws _lws;
  67. memset(&_lws, 0, sizeof(_lws));
  68. _lws.context = context;
  69. context->service_tid_detected =
  70. context->vhost_list->protocols[0].callback(
  71. &_lws, LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
  72. }
  73. context->service_tid = context->service_tid_detected;
  74. /*
  75. * is there anybody with pending stuff that needs service forcing?
  76. */
  77. if (!lws_service_adjust_timeout(context, 1, tsi)) {
  78. /* -1 timeout means just do forced service */
  79. _lws_plat_service_tsi(context, -1, pt->tid);
  80. /* still somebody left who wants forced service? */
  81. if (!lws_service_adjust_timeout(context, 1, pt->tid))
  82. /* yes... come back again quickly */
  83. timeout_ms = 0;
  84. }
  85. // n = poll(pt->fds, pt->fds_count, timeout_ms);
  86. {
  87. fd_set readfds, writefds, errfds;
  88. struct timeval tv = { timeout_ms / 1000,
  89. (timeout_ms % 1000) * 1000 };
  90. int max_fd = 0;
  91. FD_ZERO(&readfds);
  92. FD_ZERO(&writefds);
  93. FD_ZERO(&errfds);
  94. for (n = 0; n < pt->fds_count; n++) {
  95. pt->fds[n].revents = 0;
  96. if (pt->fds[n].fd >= max_fd)
  97. max_fd = pt->fds[n].fd;
  98. if (pt->fds[n].events & LWS_POLLIN)
  99. FD_SET(pt->fds[n].fd, &readfds);
  100. if (pt->fds[n].events & LWS_POLLOUT)
  101. FD_SET(pt->fds[n].fd, &writefds);
  102. FD_SET(pt->fds[n].fd, &errfds);
  103. }
  104. n = select(max_fd + 1, &readfds, &writefds, &errfds, &tv);
  105. for (n = 0; n < pt->fds_count; n++) {
  106. if (FD_ISSET(pt->fds[n].fd, &readfds))
  107. pt->fds[n].revents |= LWS_POLLIN;
  108. if (FD_ISSET(pt->fds[n].fd, &writefds))
  109. pt->fds[n].revents |= LWS_POLLOUT;
  110. if (FD_ISSET(pt->fds[n].fd, &errfds))
  111. pt->fds[n].revents |= LWS_POLLHUP;
  112. }
  113. }
  114. #ifdef LWS_OPENSSL_SUPPORT
  115. if (!pt->rx_draining_ext_list &&
  116. !lws_ssl_anybody_has_buffered_read_tsi(context, tsi) && !n) {
  117. #else
  118. if (!pt->rx_draining_ext_list && !n) /* poll timeout */ {
  119. #endif
  120. lws_service_fd_tsi(context, NULL, tsi);
  121. return 0;
  122. }
  123. faked_service:
  124. m = lws_service_flag_pending(context, tsi);
  125. if (m)
  126. c = -1; /* unknown limit */
  127. else
  128. if (n < 0) {
  129. if (LWS_ERRNO != LWS_EINTR)
  130. return -1;
  131. return 0;
  132. } else
  133. c = n;
  134. /* any socket with events to service? */
  135. for (n = 0; n < pt->fds_count && c; n++) {
  136. if (!pt->fds[n].revents)
  137. continue;
  138. c--;
  139. m = lws_service_fd_tsi(context, &pt->fds[n], tsi);
  140. if (m < 0)
  141. return -1;
  142. /* if something closed, retry this slot */
  143. if (m)
  144. n--;
  145. }
  146. return 0;
  147. }
  148. LWS_VISIBLE int
  149. lws_plat_check_connection_error(struct lws *wsi)
  150. {
  151. return 0;
  152. }
  153. LWS_VISIBLE int
  154. lws_plat_service(struct lws_context *context, int timeout_ms)
  155. {
  156. return _lws_plat_service_tsi(context, timeout_ms, 0);
  157. }
  158. LWS_VISIBLE int
  159. lws_plat_set_socket_options(struct lws_vhost *vhost, int fd)
  160. {
  161. int optval = 1;
  162. socklen_t optlen = sizeof(optval);
  163. #if defined(__APPLE__) || \
  164. defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
  165. defined(__NetBSD__) || \
  166. defined(__OpenBSD__)
  167. struct protoent *tcp_proto;
  168. #endif
  169. if (vhost->ka_time) {
  170. /* enable keepalive on this socket */
  171. optval = 1;
  172. if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
  173. (const void *)&optval, optlen) < 0)
  174. return 1;
  175. #if defined(__APPLE__) || \
  176. defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
  177. defined(__NetBSD__) || \
  178. defined(__CYGWIN__) || defined(__OpenBSD__) || defined (__sun)
  179. /*
  180. * didn't find a way to set these per-socket, need to
  181. * tune kernel systemwide values
  182. */
  183. #else
  184. /* set the keepalive conditions we want on it too */
  185. optval = vhost->ka_time;
  186. if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE,
  187. (const void *)&optval, optlen) < 0)
  188. return 1;
  189. optval = vhost->ka_interval;
  190. if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL,
  191. (const void *)&optval, optlen) < 0)
  192. return 1;
  193. optval = vhost->ka_probes;
  194. if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT,
  195. (const void *)&optval, optlen) < 0)
  196. return 1;
  197. #endif
  198. }
  199. #if 0
  200. /* Disable Nagle */
  201. optval = 1;
  202. // if (setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen) < 0)
  203. // return 1;
  204. tcp_proto = getprotobyname("TCP");
  205. if (setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, &optval, optlen) < 0)
  206. return 1;
  207. #endif
  208. /* We are nonblocking... */
  209. if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
  210. return 1;
  211. return 0;
  212. }
  213. LWS_VISIBLE void
  214. lws_plat_drop_app_privileges(struct lws_context_creation_info *info)
  215. {
  216. }
  217. LWS_VISIBLE int
  218. lws_plat_context_early_init(void)
  219. {
  220. //signal(SIGPIPE, SIG_IGN);
  221. // signal(SIGABRT, sigabrt_handler);
  222. return 0;
  223. }
  224. LWS_VISIBLE void
  225. lws_plat_context_early_destroy(struct lws_context *context)
  226. {
  227. }
  228. LWS_VISIBLE void
  229. lws_plat_context_late_destroy(struct lws_context *context)
  230. {
  231. #ifdef LWS_WITH_PLUGINS
  232. if (context->plugin_list)
  233. lws_plat_plugins_destroy(context);
  234. #endif
  235. if (context->lws_lookup)
  236. lws_free(context->lws_lookup);
  237. }
  238. /* cast a struct sockaddr_in6 * into addr for ipv6 */
  239. LWS_VISIBLE int
  240. lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,
  241. size_t addrlen)
  242. {
  243. #if 0
  244. int rc = -1;
  245. struct ifaddrs *ifr;
  246. struct ifaddrs *ifc;
  247. #ifdef LWS_USE_IPV6
  248. struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
  249. #endif
  250. getifaddrs(&ifr);
  251. for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) {
  252. if (!ifc->ifa_addr)
  253. continue;
  254. lwsl_info(" interface %s vs %s\n", ifc->ifa_name, ifname);
  255. if (strcmp(ifc->ifa_name, ifname))
  256. continue;
  257. switch (ifc->ifa_addr->sa_family) {
  258. case AF_INET:
  259. #ifdef LWS_USE_IPV6
  260. if (ipv6) {
  261. /* map IPv4 to IPv6 */
  262. bzero((char *)&addr6->sin6_addr,
  263. sizeof(struct in6_addr));
  264. addr6->sin6_addr.s6_addr[10] = 0xff;
  265. addr6->sin6_addr.s6_addr[11] = 0xff;
  266. memcpy(&addr6->sin6_addr.s6_addr[12],
  267. &((struct sockaddr_in *)ifc->ifa_addr)->sin_addr,
  268. sizeof(struct in_addr));
  269. } else
  270. #endif
  271. memcpy(addr,
  272. (struct sockaddr_in *)ifc->ifa_addr,
  273. sizeof(struct sockaddr_in));
  274. break;
  275. #ifdef LWS_USE_IPV6
  276. case AF_INET6:
  277. memcpy(&addr6->sin6_addr,
  278. &((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr,
  279. sizeof(struct in6_addr));
  280. break;
  281. #endif
  282. default:
  283. continue;
  284. }
  285. rc = 0;
  286. }
  287. freeifaddrs(ifr);
  288. if (rc == -1) {
  289. /* check if bind to IP address */
  290. #ifdef LWS_USE_IPV6
  291. if (inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1)
  292. rc = 0;
  293. else
  294. #endif
  295. if (inet_pton(AF_INET, ifname, &addr->sin_addr) == 1)
  296. rc = 0;
  297. }
  298. return rc;
  299. #endif
  300. return -1;
  301. }
  302. LWS_VISIBLE void
  303. lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
  304. {
  305. struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
  306. pt->fds[pt->fds_count++].revents = 0;
  307. }
  308. LWS_VISIBLE void
  309. lws_plat_delete_socket_from_fds(struct lws_context *context,
  310. struct lws *wsi, int m)
  311. {
  312. struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
  313. pt->fds_count--;
  314. }
  315. LWS_VISIBLE void
  316. lws_plat_service_periodic(struct lws_context *context)
  317. {
  318. }
  319. LWS_VISIBLE int
  320. lws_plat_change_pollfd(struct lws_context *context,
  321. struct lws *wsi, struct lws_pollfd *pfd)
  322. {
  323. return 0;
  324. }
  325. LWS_VISIBLE const char *
  326. lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
  327. {
  328. return inet_ntop(af, src, dst, cnt);
  329. }
  330. LWS_VISIBLE lws_fop_fd_t IRAM_ATTR
  331. _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
  332. const char *vpath, lws_fop_flags_t *flags)
  333. {
  334. struct stat stat_buf;
  335. lws_fop_fd_t fop_fd;
  336. int ret = open(filename, *flags, 0664);
  337. if (ret < 0)
  338. return NULL;
  339. if (fstat(ret, &stat_buf) < 0)
  340. goto bail;
  341. fop_fd = malloc(sizeof(*fop_fd));
  342. if (!fop_fd)
  343. goto bail;
  344. fop_fd->fops = fops;
  345. fop_fd->fd = ret;
  346. fop_fd->flags = *flags;
  347. fop_fd->filesystem_priv = NULL; /* we don't use it */
  348. fop_fd->pos = 0;
  349. fop_fd->len = stat_buf.st_size;
  350. return fop_fd;
  351. bail:
  352. close(ret);
  353. return NULL;
  354. }
  355. LWS_VISIBLE int IRAM_ATTR
  356. _lws_plat_file_close(lws_fop_fd_t *fops_fd)
  357. {
  358. int fd = (*fops_fd)->fd;
  359. free(*fops_fd);
  360. *fops_fd = NULL;
  361. return close(fd);
  362. }
  363. LWS_VISIBLE lws_fileofs_t IRAM_ATTR
  364. _lws_plat_file_seek_cur(lws_fop_fd_t fops_fd, lws_fileofs_t offset)
  365. {
  366. return lseek(fops_fd->fd, offset, SEEK_CUR);
  367. }
  368. LWS_VISIBLE int IRAM_ATTR
  369. _lws_plat_file_read(lws_fop_fd_t fops_fd, lws_filepos_t *amount,
  370. uint8_t *buf, lws_filepos_t len)
  371. {
  372. long n;
  373. n = read(fops_fd->fd, buf, len);
  374. if (n == -1) {
  375. *amount = 0;
  376. return -1;
  377. }
  378. fops_fd->pos += n;
  379. *amount = n;
  380. return 0;
  381. }
  382. LWS_VISIBLE int IRAM_ATTR
  383. _lws_plat_file_write(lws_fop_fd_t fops_fd, lws_filepos_t *amount,
  384. uint8_t *buf, lws_filepos_t len)
  385. {
  386. long n;
  387. n = write(fops_fd->fd, buf, len);
  388. if (n == -1) {
  389. *amount = 0;
  390. return -1;
  391. }
  392. fops_fd->pos += n;
  393. *amount = n;
  394. return 0;
  395. }
  396. LWS_VISIBLE int
  397. lws_plat_init(struct lws_context *context,
  398. struct lws_context_creation_info *info)
  399. {
  400. /* master context has the global fd lookup array */
  401. context->lws_lookup = lws_zalloc(sizeof(struct lws *) *
  402. context->max_fds);
  403. if (context->lws_lookup == NULL) {
  404. lwsl_err("OOM on lws_lookup array for %d connections\n",
  405. context->max_fds);
  406. return 1;
  407. }
  408. lwsl_notice(" mem: platform fd map: %5lu bytes\n",
  409. (unsigned long)(sizeof(struct lws *) * context->max_fds));
  410. #ifdef LWS_WITH_PLUGINS
  411. if (info->plugin_dirs)
  412. lws_plat_plugins_init(context, info->plugin_dirs);
  413. #endif
  414. return 0;
  415. }
  416. LWS_VISIBLE void esp32_uvtimer_cb(TimerHandle_t t)
  417. {
  418. struct timer_mapping *p = pvTimerGetTimerID(t);
  419. p->cb(p->t);
  420. }
  421. void ERR_error_string_n(unsigned long e, char *buf, size_t len)
  422. {
  423. strncpy(buf, "unknown", len);
  424. }
  425. void ERR_free_strings(void)
  426. {
  427. }
  428. char *ERR_error_string(unsigned long e, char *buf)
  429. {
  430. if (buf)
  431. strcpy(buf, "unknown");
  432. return "unknown";
  433. }
  434. /* helper functionality */
  435. #include "romfs.h"
  436. void (*lws_cb_scan_done)(void *);
  437. void *lws_cb_scan_done_arg;
  438. char lws_esp32_serial[16] = "unknown", lws_esp32_force_ap = 0,
  439. lws_esp32_region = WIFI_COUNTRY_US; // default to safest option
  440. static romfs_t lws_esp32_romfs;
  441. /*
  442. * configuration related to the AP setup website
  443. *
  444. * The 'esplws-scan' protocol drives the configuration
  445. * site, and updates the scan results in realtime over
  446. * a websocket link.
  447. */
  448. #include "../plugins/protocol_esp32_lws_scan.c"
  449. static const struct lws_protocols protocols_ap[] = {
  450. {
  451. "http-only",
  452. lws_callback_http_dummy,
  453. 0, /* per_session_data_size */
  454. 900, 0, NULL
  455. },
  456. LWS_PLUGIN_PROTOCOL_ESPLWS_SCAN,
  457. { NULL, NULL, 0, 0, 0, NULL } /* terminator */
  458. };
  459. static const struct lws_protocol_vhost_options ap_pvo = {
  460. NULL,
  461. NULL,
  462. "esplws-scan",
  463. ""
  464. };
  465. static const struct lws_http_mount mount_ap = {
  466. .mountpoint = "/",
  467. .origin = "/ap",
  468. .def = "index.html",
  469. .origin_protocol = LWSMPRO_FILE,
  470. .mountpoint_len = 1,
  471. };
  472. struct esp32_file {
  473. const struct inode *i;
  474. };
  475. esp_err_t lws_esp32_event_passthru(void *ctx, system_event_t *event)
  476. {
  477. switch(event->event_id) {
  478. case SYSTEM_EVENT_SCAN_DONE:
  479. if (lws_cb_scan_done)
  480. lws_cb_scan_done(lws_cb_scan_done_arg);
  481. break;
  482. case SYSTEM_EVENT_STA_START:
  483. esp_wifi_connect();
  484. break;
  485. case SYSTEM_EVENT_STA_DISCONNECTED:
  486. /* This is a workaround as ESP32 WiFi libs don't currently
  487. auto-reassociate. */
  488. esp_wifi_connect();
  489. break;
  490. default:
  491. break;
  492. }
  493. return ESP_OK;
  494. }
  495. static lws_fop_fd_t IRAM_ATTR
  496. esp32_lws_fops_open(const struct lws_plat_file_ops *fops, const char *filename,
  497. const char *vfs_path, lws_fop_flags_t *flags)
  498. {
  499. struct esp32_file *f = malloc(sizeof(*f));
  500. lws_fop_fd_t fop_fd;
  501. size_t len;
  502. lwsl_notice("%s: %s\n", __func__, filename);
  503. if (!f)
  504. return NULL;
  505. f->i = romfs_get_info(lws_esp32_romfs, filename, &len);
  506. if (!f->i)
  507. goto bail;
  508. fop_fd = malloc(sizeof(*fop_fd));
  509. if (!fop_fd)
  510. goto bail;
  511. fop_fd->fops = fops;
  512. fop_fd->filesystem_priv = f;
  513. fop_fd->flags = *flags;
  514. fop_fd->len = len;
  515. fop_fd->pos = 0;
  516. return fop_fd;
  517. bail:
  518. free(f);
  519. return NULL;
  520. }
  521. static int IRAM_ATTR
  522. esp32_lws_fops_close(lws_fop_fd_t *fop_fd)
  523. {
  524. free((*fop_fd)->filesystem_priv);
  525. free(*fop_fd);
  526. *fop_fd = NULL;
  527. return 0;
  528. }
  529. static lws_fileofs_t IRAM_ATTR
  530. esp32_lws_fops_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset_from_cur_pos)
  531. {
  532. fop_fd->pos += offset_from_cur_pos;
  533. if (fop_fd->pos > fop_fd->len)
  534. fop_fd->pos = fop_fd->len;
  535. return 0;
  536. }
  537. static int IRAM_ATTR
  538. esp32_lws_fops_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount, uint8_t *buf,
  539. lws_filepos_t len)
  540. {
  541. struct esp32_file *f = fop_fd->filesystem_priv;
  542. if ((long)buf & 3) {
  543. lwsl_err("misaligned buf\n");
  544. return -1;
  545. }
  546. if (fop_fd->pos >= fop_fd->len)
  547. return 0;
  548. if (len > fop_fd->len - fop_fd->pos)
  549. len = fop_fd->len - fop_fd->pos;
  550. spi_flash_read((uint32_t)(char *)f->i + fop_fd->pos, buf, len);
  551. *amount = len;
  552. fop_fd->pos += len;
  553. return 0;
  554. }
  555. static const struct lws_plat_file_ops fops = {
  556. .LWS_FOP_OPEN = esp32_lws_fops_open,
  557. .LWS_FOP_CLOSE = esp32_lws_fops_close,
  558. .LWS_FOP_READ = esp32_lws_fops_read,
  559. .LWS_FOP_SEEK_CUR = esp32_lws_fops_seek_cur,
  560. };
  561. static wifi_config_t sta_config = {
  562. .sta = {
  563. .bssid_set = false
  564. }
  565. }, ap_config = {
  566. .ap = {
  567. .channel = 6,
  568. .authmode = WIFI_AUTH_OPEN,
  569. .max_connection = 1,
  570. }
  571. };
  572. void
  573. lws_esp32_wlan_config(void)
  574. {
  575. nvs_handle nvh;
  576. char r[2];
  577. size_t s;
  578. ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh));
  579. s = sizeof(sta_config.sta.ssid) - 1;
  580. if (nvs_get_str(nvh, "ssid", (char *)sta_config.sta.ssid, &s) != ESP_OK)
  581. lws_esp32_force_ap = 1;
  582. s = sizeof(sta_config.sta.password) - 1;
  583. if (nvs_get_str(nvh, "password", (char *)sta_config.sta.password, &s) != ESP_OK)
  584. lws_esp32_force_ap = 1;
  585. s = sizeof(lws_esp32_serial) - 1;
  586. if (nvs_get_str(nvh, "serial", lws_esp32_serial, &s) != ESP_OK)
  587. lws_esp32_force_ap = 1;
  588. else
  589. snprintf((char *)ap_config.ap.ssid, sizeof(ap_config.ap.ssid) - 1,
  590. "config-%s-%s", lws_esp32_model, lws_esp32_serial);
  591. s = sizeof(r);
  592. if (nvs_get_str(nvh, "region", r, &s) != ESP_OK)
  593. lws_esp32_force_ap = 1;
  594. else
  595. lws_esp32_region = atoi(r);
  596. nvs_close(nvh);
  597. tcpip_adapter_init();
  598. }
  599. void
  600. lws_esp32_wlan_start(void)
  601. {
  602. wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  603. ESP_ERROR_CHECK( esp_wifi_init(&cfg));
  604. ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM));
  605. ESP_ERROR_CHECK( esp_wifi_set_country(lws_esp32_region));
  606. if (!lws_esp32_is_booting_in_ap_mode() && !lws_esp32_force_ap) {
  607. ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA));
  608. ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config));
  609. } else {
  610. ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_APSTA) );
  611. ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_AP, &ap_config) );
  612. }
  613. ESP_ERROR_CHECK( esp_wifi_start());
  614. tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, (const char *)&ap_config.ap.ssid[7]);
  615. if (!lws_esp32_is_booting_in_ap_mode() && !lws_esp32_force_ap)
  616. ESP_ERROR_CHECK( esp_wifi_connect());
  617. }
  618. struct lws_context *
  619. lws_esp32_init(struct lws_context_creation_info *info, unsigned int _romfs)
  620. {
  621. size_t romfs_size;
  622. struct lws_context *context;
  623. lws_set_log_level(65535, lwsl_emit_syslog);
  624. context = lws_create_context(info);
  625. if (context == NULL) {
  626. lwsl_err("Failed to create context\n");
  627. return NULL;
  628. }
  629. lws_esp32_romfs = (romfs_t)(void *)_romfs;
  630. romfs_size = romfs_mount_check(lws_esp32_romfs);
  631. if (!romfs_size) {
  632. lwsl_err("Failed to mount ROMFS\n");
  633. return NULL;
  634. }
  635. lwsl_notice("ROMFS length %uKiB\n", romfs_size >> 10);
  636. /* set the lws vfs to use our romfs */
  637. lws_set_fops(context, &fops);
  638. if (lws_esp32_is_booting_in_ap_mode() || lws_esp32_force_ap) {
  639. info->vhost_name = "ap";
  640. info->protocols = protocols_ap;
  641. info->mounts = &mount_ap;
  642. info->pvo = &ap_pvo;
  643. }
  644. if (!lws_create_vhost(context, info))
  645. lwsl_err("Failed to create vhost\n");
  646. lws_protocol_init(context);
  647. return context;
  648. }