1/*
2 * lws-minimal-esp32
3 *
4 * Written in 2010-2020 by Andy Green <andy@warmcat.com>
5 *
6 * This file is made available under the Creative Commons CC0 1.0
7 * Universal Public Domain Dedication.
8 *
9 * Based on espressif Public Domain sample
10 */
11
12#define LWIP_PROVIDE_ERRNO 1
13#define _ESP_PLATFORM_ERRNO_H_
14
15#include <stdio.h>
16#include "sdkconfig.h"
17#include "freertos/FreeRTOS.h"
18#include "freertos/task.h"
19
20#include <driver/gpio.h>
21
22#include <libwebsockets.h>
23
24struct lws_context *context;
25extern struct lws_led_state *lls;
26extern lws_display_state_t lds;
27extern lws_netdev_instance_wifi_t *wnd;
28
29extern int init_plat_devices(struct lws_context *);
30
31#include "policy.h"
32
33static uint8_t flip;
34
35typedef struct myss {
36	struct lws_ss_handle 		*ss;
37	void				*opaque_data;
38	/* ... application specific state ... */
39
40	size_t				amount;
41
42} myss_t;
43
44static int
45myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags)
46{
47	myss_t *m = (myss_t *)userobj;
48
49	lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags);
50//	lwsl_hexdump_info(buf, len);
51	m->amount += len;
52
53	if (flags & LWSSS_FLAG_EOM) {
54
55		/*
56		 * If we received the whole message, for our example it means
57		 * we are done.
58		 */
59
60		lwsl_notice("%s: received %u bytes\n", __func__,
61			    (unsigned int)m->amount);
62
63		/*
64		 * In CI, we use sai-expect to look for this
65		 * string for success
66		 */
67
68		lwsl_notice("Completed: PASS\n");
69	}
70
71	return 0;
72}
73
74static int
75myss_state(void *userobj, void *sh, lws_ss_constate_t state,
76	   lws_ss_tx_ordinal_t ack)
77{
78	myss_t *m = (myss_t *)userobj;
79
80	lwsl_user("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state),
81		  (unsigned int)ack);
82
83	switch (state) {
84	case LWSSSCS_CREATING:
85		if (lws_ss_client_connect(m->ss))
86			lwsl_err("%s: connection failed\n", __func__);
87		break;
88	default:
89		break;
90	}
91
92	return 0;
93}
94
95static const lws_ss_info_t ssi = {
96	.handle_offset			= offsetof(myss_t, ss),
97	.opaque_user_data_offset	= offsetof(myss_t, opaque_data),
98	.rx				= myss_rx,
99	.state				= myss_state,
100	.user_alloc			= sizeof(myss_t),
101	.streamtype			= "test_stream",
102};
103
104static const lws_led_sequence_def_t *seqs[] = {
105	&lws_pwmseq_static_on,
106	&lws_pwmseq_static_off,
107	&lws_pwmseq_sine_endless_slow,
108	&lws_pwmseq_sine_endless_fast,
109};
110
111static int
112smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, void *buf,
113       size_t len)
114{
115
116	if (!lws_json_simple_strcmp(buf, len, "\"src\":", "bc/user") &&
117	    !lws_json_simple_strcmp(buf, len, "\"event\":", "click")) {
118		lws_led_transition(lls, "alert", seqs[flip & 3],
119				   &lws_pwmseq_linear_wipe);
120		flip++;
121	}
122
123	lwsl_hexdump_notice(buf, len);
124
125	if ((_class & LWSSMDCL_SYSTEM_STATE) &&
126	    !lws_json_simple_strcmp(buf, len, "\"state\":", "OPERATIONAL")) {
127
128		/* create the secure stream */
129
130		lwsl_notice("%s: creating test secure stream\n", __func__);
131
132		if (lws_ss_create(context, 0, &ssi, NULL, NULL, NULL, NULL)) {
133			lwsl_err("%s: failed to create secure stream\n",
134				 __func__);
135			return -1;
136		}
137	}
138
139	if (_class & LWSSMDCL_INTERACTION)
140		/*
141		 * Any kind of user interaction brings the display back up and
142		 * resets the dimming / blanking timers
143		 */
144		lws_display_state_active(&lds);
145
146	return 0;
147}
148
149void
150app_main(void)
151{
152	struct lws_context_creation_info *info;
153
154	lws_set_log_level(1024 | 7, NULL);
155
156        lws_netdev_plat_init();
157        lws_netdev_plat_wifi_init();
158
159        info = malloc(sizeof(*info));
160        if (!info)
161        	goto spin;
162
163	memset(info, 0, sizeof(*info));
164
165	lwsl_notice("LWS test for ESP32-C3 Dev Board\n");
166
167	info->pss_policies_json		= ss_policy;
168	info->options			= LWS_SERVER_OPTION_EXPLICIT_VHOSTS |
169					  LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
170	info->port			= CONTEXT_PORT_NO_LISTEN;
171	info->early_smd_cb		= smd_cb;
172	info->early_smd_class_filter	= LWSSMDCL_INTERACTION |
173					  LWSSMDCL_SYSTEM_STATE |
174					  LWSSMDCL_NETWORK;
175
176	context = lws_create_context(info);
177	if (!context) {
178		lwsl_err("lws init failed\n");
179		return;
180	}
181
182	/*
183	 * We don't need this after context creation... things it pointed to
184	 * still need to exist though since the context copied the pointers.
185	 */
186
187	free(info);
188
189	/* devices and init are in devices.c */
190
191	if (init_plat_devices(context))
192		goto spin;
193
194
195	/* the lws event loop */
196
197	do {
198		taskYIELD();
199	} while (lws_service(context, 0) >= 0);
200
201
202spin:
203	vTaskDelay(10);
204	taskYIELD();
205	goto spin;
206}
207