• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * Configured for ESP32 WROVER KIT
10  *
11  * What should be notable about this is there are no esp-idf apis used here or
12  * any related files, despite we are running on top of stock esp-idf.
13  */
14 
15 #define LWIP_PROVIDE_ERRNO 1
16 #define _ESP_PLATFORM_ERRNO_H_
17 
18 #include <stdio.h>
19 #include "sdkconfig.h"
20 #include "freertos/FreeRTOS.h"
21 #include "freertos/task.h"
22 
23 #include <driver/gpio.h>
24 
25 #include <libwebsockets.h>
26 
27 struct lws_context *context;
28 extern struct lws_led_state *lls;
29 extern lws_display_state_t lds;
30 extern struct lws_button_state *bcs;
31 extern lws_netdev_instance_wifi_t *wnd;
32 
33 lws_sorted_usec_list_t		sul_pass;
34 
35 extern int init_plat_devices(struct lws_context *);
36 
37 static const uint8_t logo[] = {
38 #include "cat-565.h"
39 };
40 
41 #if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
42 #include "static-policy.h"
43 #else
44 #include "policy.h"
45 #endif
46 
47 static uint8_t flip;
48 
49 
50 typedef struct myss {
51 	struct lws_ss_handle 		*ss;
52 	void				*opaque_data;
53 	/* ... application specific state ... */
54 
55 	size_t				amount;
56 
57 } myss_t;
58 
59 /*
60  * When we're actually happy we passed, we schedule the actual pass
61  * string to happen a few seconds later, so we can observe what the
62  * code did after the pass.
63  */
64 
65 static void
completion_sul_cb(lws_sorted_usec_list_t * sul)66 completion_sul_cb(lws_sorted_usec_list_t *sul)
67 {
68 	/*
69 	 * In CI, we use sai-expect to look for this
70 	 * string for success
71 	 */
72 
73 	lwsl_notice("Completed: PASS\n");
74 }
75 
76 static int
myss_rx(void * userobj,const uint8_t * buf,size_t len,int flags)77 myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags)
78 {
79 	myss_t *m = (myss_t *)userobj;
80 
81 	lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags);
82 //	lwsl_hexdump_info(buf, len);
83 	m->amount += len;
84 
85 	if (flags & LWSSS_FLAG_EOM) {
86 
87 		/*
88 		 * If we received the whole message, for our example it means
89 		 * we are done.
90 		 *
91 		 * Howevere we want to record what happened after we received
92 		 * the last bit so we can see anything unexpected coming.  So
93 		 * wait 5s before sending the PASS magic.
94 		 */
95 
96 		lwsl_notice("%s: received %u bytes, passing in 10s\n",
97 			    __func__, (unsigned int)m->amount);
98 
99 		lws_sul_schedule(context, 0, &sul_pass, completion_sul_cb,
100 				 5 * LWS_US_PER_SEC);
101 
102 		return LWSSSSRET_DESTROY_ME;
103 	}
104 
105 	return 0;
106 }
107 
108 static int
myss_state(void * userobj,void * sh,lws_ss_constate_t state,lws_ss_tx_ordinal_t ack)109 myss_state(void *userobj, void *sh, lws_ss_constate_t state,
110 	   lws_ss_tx_ordinal_t ack)
111 {
112 	myss_t *m = (myss_t *)userobj;
113 
114 	lwsl_user("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state),
115 		  (unsigned int)ack);
116 
117 	switch (state) {
118 	case LWSSSCS_CREATING:
119 		lws_ss_client_connect(m->ss);
120 		break;
121 	default:
122 		break;
123 	}
124 
125 	return 0;
126 }
127 
128 static const lws_ss_info_t ssi = {
129 	.handle_offset			= offsetof(myss_t, ss),
130 	.opaque_user_data_offset	= offsetof(myss_t, opaque_data),
131 	.rx				= myss_rx,
132 	.state				= myss_state,
133 	.user_alloc			= sizeof(myss_t),
134 	.streamtype			= "test_stream",
135 };
136 
137 static const lws_led_sequence_def_t *seqs[] = {
138 	&lws_pwmseq_static_on,
139 	&lws_pwmseq_static_off,
140 	&lws_pwmseq_sine_endless_slow,
141 	&lws_pwmseq_sine_endless_fast,
142 };
143 
144 static int
smd_cb(void * opaque,lws_smd_class_t _class,lws_usec_t timestamp,void * buf,size_t len)145 smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, void *buf,
146        size_t len)
147 {
148 
149 	if (!lws_json_simple_strcmp(buf, len, "\"src\":", "bc/user") &&
150 	    !lws_json_simple_strcmp(buf, len, "\"event\":", "click")) {
151 		lws_led_transition(lls, "blue", seqs[flip & 3],
152 				   &lws_pwmseq_linear_wipe);
153 		flip++;
154 	}
155 
156 	lwsl_hexdump_notice(buf, len);
157 
158 	if ((_class & LWSSMDCL_SYSTEM_STATE) &&
159 	    !lws_json_simple_strcmp(buf, len, "\"state\":", "OPERATIONAL")) {
160 
161 		/* create the secure stream */
162 
163 		lwsl_notice("%s: creating test secure stream\n", __func__);
164 
165 		if (lws_ss_create(context, 0, &ssi, NULL, NULL, NULL, NULL)) {
166 			lwsl_err("%s: failed to create secure stream\n",
167 				 __func__);
168 			return -1;
169 		}
170 	}
171 
172 	if (_class & LWSSMDCL_INTERACTION)
173 		/*
174 		 * Any kind of user interaction brings the display back up and
175 		 * resets the dimming / blanking timers
176 		 */
177 		lws_display_state_active(&lds);
178 
179 	return 0;
180 }
181 
182 void
app_main(void)183 app_main(void)
184 {
185 	struct lws_context_creation_info *info;
186 
187 	lws_set_log_level(1024 | 15, NULL);
188 
189         lws_netdev_plat_init();
190         lws_netdev_plat_wifi_init();
191 
192         info = malloc(sizeof(*info));
193         if (!info)
194         	goto spin;
195 
196 	memset(info, 0, sizeof(*info));
197 
198 	lwsl_notice("LWS test for Espressif ESP32 WROVER KIT\n");
199 
200 #if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
201 	info->pss_policies_json		= ss_policy;
202 #else
203 	info->pss_policies		= &_ss_static_policy_entry;
204 #endif
205 	info->options			= LWS_SERVER_OPTION_EXPLICIT_VHOSTS |
206 					  LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
207 	info->port			= CONTEXT_PORT_NO_LISTEN;
208 	info->early_smd_cb		= smd_cb;
209 	info->early_smd_class_filter	= LWSSMDCL_INTERACTION |
210 					  LWSSMDCL_SYSTEM_STATE |
211 					  LWSSMDCL_NETWORK;
212 	info->smd_ttl_us		= 20 * LWS_USEC_PER_SEC; /* we can spend a long time in display */
213 
214 	context = lws_create_context(info);
215 	if (!context) {
216 		lwsl_err("lws init failed\n");
217 		goto spin;
218 	}
219 
220 	/*
221 	 * We don't need this after context creation... things it pointed to
222 	 * still need to exist though since the context copied the pointers.
223 	 */
224 
225 	free(info);
226 
227 	/* devices and init are in devices.c */
228 
229 	if (init_plat_devices(context))
230 		goto spin;
231 
232 	/* put the cat picture up there and enable the backlight */
233 
234 	lds.disp->blit(lds.disp, logo, 0, 0, 320, 240);
235 	lws_display_state_active(&lds);
236 
237 	/* the lws event loop */
238 
239 	do {
240 		taskYIELD();
241 		lws_service(context, 0);
242 	} while (1);
243 
244 	lwsl_notice("%s: exited event loop\n", __func__);
245 
246 
247 spin:
248 	vTaskDelay(10);
249 	taskYIELD();
250 	goto spin;
251 }
252