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