SingingCat 0
application
usb.c
1#include "main-header.h"
2#include "loader-api.h"
3#include "addressing.h"
4#include "espressif/esp8266_flash.h"
5#include "powersave.h"
6#include "proto-esp-usart.h"
7#include "multiram.h"
8#include "platform-header.h"
9#include "wireless_state_machine.h"
10#include "streams.h"
11#include "usb.h"
12#include "flashapp.h"
13#include "app_update.h"
14#include "metrics/metrics.h"
15#include "hijack.h"
16struct mculib_acm acm;
17
18static int esp_bridge_mode = 0;
19uint32_t acm_byte_received;
20extern struct ringbuffer console_ringbuffer;
21
22// we add bytes received from usb into the serial port buffer
23// we share a buffer, so if we DO receive a byte from USB, we temporarily
24// stop storing any bytes from serial port
25void usb_byte_received(byte b) {
26 uint8_t buf[1];
27
28 buf[0] = b;
29 if (hijack_receive_on_usb_acm((uint8_t *)&buf, 1)) {
30 return;
31 }
32
33 IncMetric_METRIC_IRQ_USB;
34 acm_byte_received = 500;
35 console_add_byte(b);
36}
37
38void usb_restore_irq() {
39 mculib_usb_set_received_callback(MAIN_MCULIBHANDLE, usb_byte_received);
40}
41
42void usb_start() {
43 memset(&acm, 0, sizeof(acm));
44 uint64_t modid = config_get_moduleid();
45
46 if (modid == 0) {
47 acm.serial[0] = 'n';
48 acm.serial[1] = '-';
49 node_to_str(get_my_node_id(), acm.serial + 2);
50 } else {
51 acm.serial[0] = 'm';
52 acm.serial[1] = '-';
53 snprintf(acm.serial + 2, 11, "%i", (int)modid);
54 }
55 //strncpy(acm.serial,"000E000002",12);
56 //strncpy(acm.serial,"00000E000002",12);
57 strncpy(acm.product, "module v3", 16);
58 acm.usb_callback = NULL;
59 acm.usb_received_callback = &usb_byte_received;
60 mculib_enable_usb_acm(MAIN_MCULIBHANDLE, &acm);
61}
62
63/***************************** app update stuff ***********************************/
64/*
65 * the packet is simple:
66 *
67 * sender (host to singingcat)
68 * start upload:
69 * [uint8 ] 0xFF control
70 * [uint8 ] 0x06 start_upload
71 * [uint16] packet number (must be consecutive!)
72 * [uint32] baseaddress
73 *
74 * data packet:
75 * [uint8 ] 0xFF control
76 * [uint8 ] 0x01: start data
77 * [uint16] packet number (must be consecutive!)
78 * [uint8 ] header length (how many bytes to skip to arrive at first data byte)
79 * [uint16] data length
80 * [uint32] crc32 checksum (over data only)
81 *
82 * just sync: (no replies expected) (sent by module if idle)
83 * [uint8 ] 0xFF control
84 * [uint8 ] 0x02: start data
85 *
86 * done:
87 * [uint8 ] 0xFF control
88 * [uint8 ] 0x05 done
89 * [uint16] packet number (must be consecutive!)
90 * [uint32] length in bytes
91 * [uint32] total checksum
92 * [uint8] flags (none defined atm)
93 *
94 * replies (singingcat to host):
95 * ACK
96 * [uint8 ] 0xFF control
97 * [uint8 ] 0x03 ACK
98 * [uint16] packet number
99 * [uint32] extra data (depends on what is being acked)
100 * NACK
101 * [uint8 ] 0xFF control
102 * [uint8 ] 0x04 NACK
103 * [uint16] packet number
104 * [uint8 ] error code
105 * [uint32] extra
106 *
107 * various actions (sent host->module)
108 * [uint8 ] 0xFF control
109 * [uint8] 0x07 perform an action
110 * [uint32] # of action to perform
111 * [uint32] # data to pass to action
112 *
113 * various actions with data (sent host->module)
114 * [uint8 ] 0xFF control
115 * [uint8] 0x08 perform an action with data
116 * [uint32] # of data-action to perform
117 * [uint32] number of bytes to follow
118 * bytes # data to pass to action
119 *
120 * actions:
121 * 1 reset
122 * 2 running (returns current baseaddress in extra)
123 * 3 setlatest (sets actiondata baseaddress to be latest in loader, returns new seq in extra)
124 * 4 abort usb flash
125 * 5 restart usb flash
126 * 6 get nodeid
127 * 7 get version
128 * 8 set wifi chip to flash mode and bridge its serial port to usb
129 *
130 * actions with data
131 * 1 set wifi ssid (data == ssid-nul-password)
132 * 2 set cloudtoken
133 */
134#ifdef usb_app_debug
135#define SENDTOUSB simulate_send_to_usb
136#else
137#define SENDTOUSB send_usb
138#endif
139
140const static char *ready = "[USB_APPFLASH]\r\n";
141static byte pleasestop;
142static byte *usbbuf;
143static void *baseaddr; // baseaddr advertised on start packet
144static uint32_t flash_flags; // flags set on start packet
145static uint32_t total_size; // total size
146static int curpos = 0;
147static byte state;
148static byte packet_ready = 0;
149struct usb_app_packet curpacket;
150static uint16_t lastpack = 0;
151static uint32_t received = 0;
152static long timer_ts = 0;
153static byte ackbuf[10];
154static byte started = 0;
155static int pctr; // count every 2 seconds roughly
156// for howlong do we allow idle (== no packets received) before aborting?
157#define MAX_SECS_USBFLASH 20
158
159#ifdef usb_app_debug
160uint8_t usbdebugmode = 1;
161void usbdebugf(char *format, ...) {
162 va_list args;
163
164 if (!usbdebugmode) {
165 return;
166 }
167
168 va_start(args, format);
169 vprintf(format, args);
170 va_end(args);
171}
172#endif
173static void preerase(void *adr, uint32_t size);
174void print_usb_app_packet(struct usb_app_packet *pack) {
175#ifdef usb_app_debug
176 if (pack->type == 0x06) {
177 usbdebugf("[usbapp] Packet #0x%x START_UPLOAD: base=0x%X\r\n", pack->number, pack->start_upload.base);
178 } else if (pack->type == 0x03) {
179 usbdebugf("[usbapp] Packet #0x%x ACK\r\n", pack->number);
180 } else if (pack->type == 0x04) {
181 usbdebugf("[usbapp] Packet #0x%x NACK (code=%i)\r\n", pack->number, pack->nack.code);
182 } else if (pack->type == 0x01) {
183 usbdebugf("[usbapp] Packet #0x%x DATA: len=0x%X, checksum=0x%0X\r\n", pack->number, pack->data.data_length, pack->data.checksum);
184 } else if (pack->type == 0x05) {
185 usbdebugf("[usbapp] Packet #0x%x DONE, checksum=0x%X, len=%i,flags=%i\r\n", pack->number, pack->done.checksum, pack->done.len, pack->done.flags);
186 } else if (pack->type == 0x07) {
187 usbdebugf("[usbapp] Packet #0x%x ACTION, action=0x%X\r\n", pack->number, pack->action.action);
188 } else if (pack->type == 0x08) {
189 usbdebugf("[usbapp] Packet #0x%x ACTION_WITH_DATA, action=0x%X\r\n", pack->number, pack->action.action);
190 } else {
191 usbdebugf("[usbapp] Packet type=0x%x\r\n", pack->type);
192 }
193#endif
194}
195
196uint32_t parse32(byte *tmpbuf, int offset) {
197 uint32_t res;
198
199 res = (tmpbuf[offset++] & 0xFF);
200 res = (res << 8) | (tmpbuf[offset++] & 0xFF);
201 res = (res << 8) | (tmpbuf[offset++] & 0xFF);
202 res = (res << 8) | (tmpbuf[offset++] & 0xFF);
203 return res;
204}
205uint16_t parse16(byte *tmpbuf, int offset) {
206 uint16_t res;
207
208 res = (tmpbuf[offset++] & 0xFF);
209 res = (res << 8) | (tmpbuf[offset++] & 0xFF);
210 return res;
211}
212// expects headersize & type to be available in target
213int usb_app_parse(byte *tmpbuf, int size, struct usb_app_packet *target) {
214#ifdef usb_app_debug
215 usbdebugf("[usbapp] Parsing struct from %i bytes, type %i\n", size, target->type);
216#endif
217 if (target->type == 0x06) { // start
218 target->number = parse16(tmpbuf, 0);
219 target->start_upload.base = parse32(tmpbuf, 2);
220 target->start_upload.flags = parse32(tmpbuf, 6);
221 target->start_upload.size = parse32(tmpbuf, 10);
222 return 0;
223 }
224 if (target->type == 0x05) { // done
225 target->number = parse16(tmpbuf, 0);
226 target->done.checksum = parse32(tmpbuf, 2);
227 target->done.len = parse32(tmpbuf, 6);
228 target->done.flags = tmpbuf[10];
229 return 0;
230 }
231 if (target->type == 0x07) { // action
232 target->number = parse16(tmpbuf, 0);
233 target->action.action = parse32(tmpbuf, 2);
234 target->action.actiondata = parse32(tmpbuf, 6);
235 return 0;
236 }
237 if (target->type == 0x08) { // action with data
238 target->number = parse16(tmpbuf, 0);
239 target->action.action = parse32(tmpbuf, 2);
240 target->action.datalen = parse32(tmpbuf, 6);
241 return 0;
242 }
243 if (target->type == 0x01) { // data
244 target->number = parse16(tmpbuf, 0);
245 target->data.header_length = tmpbuf[2];
246 target->data.data_length = parse16(tmpbuf, 3);
247 target->data.checksum = parse32(tmpbuf, 5);
248 return 0;
249 }
250 if (target->type == 0x04) {
251 target->number = parse16(tmpbuf, 0);
252 target->nack.code = tmpbuf[2];
253 target->nack.extra = parse32(tmpbuf, 3);
254 return 0;
255 }
256 if (target->type == 0x03) {
257 target->number = parse16(tmpbuf, 0);
258 target->ack.extra = parse32(tmpbuf, 2);
259 return 0;
260 }
261
262#ifdef usb_app_debug
263 usbdebugf("[usbapp] Parsing struct failed from %i bytes, inv type: %i\n", size, target->type);
264#endif
265 return 5;
266}
267
268void usb_appupdate_byte_received(byte b) {
269#ifdef usb_app_debug
270 if (curpacket.type != 0x01) {
271 usbdebugf("[usbapp] State: %i, Pos: %i, Headersize=%i, Received 0x%x\n", state, curpos, curpacket.headersize, b);
272 }
273#endif
274 // if we're in state 0, only accept new packets...
275 if (state == 0) {
276 if (b != 0xFF) {
277 return;
278 }
279 state = 1;
280 curpos = 0;
281 packet_ready = 0;
282#ifdef usb_app_debug
283 usbdebugf("[usbapp] Command start\n");
284#endif
285 return;
286 } else if (state == 1) {
287 curpacket.type = b;
288#ifdef usb_app_debug
289 usbdebugf("[usbapp] Command type %i\n", curpacket.type);
290#endif
291 state = 2;
292 curpacket.datasize = 0;
293 // headersize (from type onwards)
294 if (curpacket.type == 0x06) { // start
295 curpacket.headersize = 14;
296 } else if (curpacket.type == 0x07) { // action
297 curpacket.headersize = 10;
298 } else if (curpacket.type == 0x08) { // action with data
299 curpacket.headersize = 10;
300 } else if (curpacket.type == 0x01) { // data
301 curpacket.headersize = 9;
302 } else if (curpacket.type == 0x05) { //done
303 curpacket.headersize = 11;
304 } else if (curpacket.type == 0x04) { // nack
305 curpacket.headersize = 7;
306 } else {
307 printf("Invpackettype %i\r\n", curpacket.type);
308 state = 0;
309 }
310 return;
311 } else if (state == 2) {
312 usbbuf[curpos] = b;
313 curpos++;
314 if (curpos >= curpacket.headersize) {
315#ifdef usb_app_debug
316 usbdebugf("[usbapp] command(header) completed\n");
317#endif
318 int i = usb_app_parse(usbbuf, curpos, &curpacket);
319 if (i != 0) {
320#ifdef usb_app_debug
321 usbdebugf("[usbapp] parse failed: %i\n", i);
322#endif
323 state = 0;
324 return;
325 }
326 print_usb_app_packet(&curpacket);
327 state = 3;
328 if ((curpacket.type == 0x01) || (curpacket.type == 0x08)) { // var data in these packets
329 curpos = 0;
330 } else {
331 packet_ready = 1;
332 }
333 }
334 } else if (state == 3) {
335 if (curpacket.type == 0x01) { // var-len data packet?
336 usbbuf[curpos] = b;
337 curpos++;
338 if (curpos < curpacket.data.data_length) {
339 return;
340 }
341 packet_ready = 1;
342 state = 5;
343 return;
344 } else if (curpacket.type == 0x08) { // var-len actiondata packet?
345 usbbuf[curpos] = b;
346 curpos++;
347 if (curpos < curpacket.action.datalen) {
348 return;
349 }
350 packet_ready = 1;
351 state = 5;
352 return;
353 }
354
355 printf("packet too early.\r\n");
356 state = 0;
357 } else {
358 printf("Inv state %i\r\n", state);
359 state = 0;
360 }
361}
362
363static void send_usb(int len, byte *b) {
364 int i;
365
366 i = mculib_usb_send(MAIN_MCULIBHANDLE, len, b);
367 if (i != len) {
368 printf("USB send fail %i!=%i\r\n", b, i);
369 }
370}
371
372static void sendsync() {
373 byte b[3];
374
375 SENDTOUSB(strlen(ready), (byte *)ready);
376 b[0] = 0xFF;
377 b[1] = 0x02;
378 b[2] = '\n';
379 SENDTOUSB(3, b);
380 printf("idle sync\r\n");
381}
382static void add32(byte *buf, int offset, uint32_t value) {
383 buf[offset++] = (value >> 24) & 0xFF;
384 buf[offset++] = (value >> 16) & 0xFF;
385 buf[offset++] = (value >> 8) & 0xFF;
386 buf[offset++] = (value) & 0xFF;
387}
388
389void usb_app_update_ack(struct usb_app_packet *pack, uint32_t extra) {
390#ifdef usb_app_debug
391 usbdebugf("[usbapp] [usbapp] ack type %i, seq=%i,extra=%i\r\n", pack->type, pack->number, extra);
392#endif
393 ackbuf[0] = 0xFF;
394 ackbuf[1] = 0x03;
395 ackbuf[2] = (pack->number >> 8) & 0xFF;
396 ackbuf[3] = (pack->number) & 0xFF;
397 add32(ackbuf, 4, extra);
398 ackbuf[8] = '\r';
399 ackbuf[9] = '\n';
400 SENDTOUSB(10, ackbuf);
401}
402void usb_app_update_nack(struct usb_app_packet *pack, uint8_t code, uint32_t extra) {
403#ifdef usb_app_debug
404 usbdebugf("[usbapp] nack type %i, seq=%i: %i\r\n", pack->type, pack->number, code);
405#endif
406 ackbuf[0] = 0xFF;
407 ackbuf[1] = 0x04;
408 ackbuf[2] = (pack->number >> 8) & 0xFF;
409 ackbuf[3] = (pack->number) & 0xFF;
410 ackbuf[4] = code;
411 add32(ackbuf, 5, extra);
412 ackbuf[9] = '\n';
413 SENDTOUSB(10, ackbuf);
414}
415static void reinit() {
416 pctr = 0;
417 started = 0;
418 curpos = 0;
419 state = 0;
420 lastpack = 0;
421 received = 0;
422 timer_ts = 0;
423}
424/**************************************************
425* \\brief process action packets arriving on usb
426* returns 0 if ok, otherwise errorcode. extra will be set to some extra value
427**************************************************/
428static int runaction_data(uint32_t action, uint32_t datalen, uint32_t *extra) {
429 // data in 'usbbuf'
430 usbbuf[datalen] = 0;
431 // printf("usbbuf (%i): \"%s\"\r\n",datalen,usbbuf);
432 char *line = (char *)usbbuf;
433
434 if (action == 1) { // set ssid
435 int i;
436 for (i = 0; i < datalen; i++) {
437 if (line[i] == 0) {
438 printf("setting ssid to \"%s\" with password \"%s\"\r\n", line, line + i + 1);
439 esp8266_add_ap(line, line + i + 1);
440 break;
441 }
442 }
444 *extra = 0;
445 } else if (action == 2) { // set cloudtoken
446 config_set_cloud_token(line);
447 config_commit();
448 *extra = 0;
449 }
450 return 0;
451}
452/**************************************************
453* \\brief process action packets arriving on usb
454* returns 0 if ok, otherwise errorcode. extra will be set to some extra value
455**************************************************/
456static int runaction(uint32_t action, uint32_t data, uint32_t *extra) {
457#ifdef usb_app_debug
458 usbdebugf("[usbapp] action %i, data %i\r\n", action, data);
459#endif
460 *extra = 0;
461 if (action == 1) {
462 reboot_hard(); // won't send an answer...
463 }
464 if (action == 2) {
465 *extra = (uint32_t)get_app_header();
466#ifdef usb_app_debug
467 usbdebugf("[usbapp] action request for base address: 0x%p\n", *extra);
468#endif
469 } else if (action == 3) {
470 int r = set_latest_app((void *)data);
471 if (r != 0) {
472 return r;
473 }
474 struct meta_header *m = get_other_meta_header((void *)data);
475 if (m == NULL) {
476 return 44;
477 }
478 *extra = m->meta_seq;
479 } else if (action == 5) {
480 reinit();
481 } else if (action == 4) {
482 pleasestop = 1;
483 // 5 is special and not here
484 } else if (action == 6) {
485 *extra = get_my_node_id();
486 } else if (action == 7) {
487 *extra = CNW_BUILD_VERSION;
488 } else if (action == 8) {
489 // wifi update
490 int wf = esp8266_get_firmware_version();
491 esp_bridge_mode = 1;
492 usb_app_update_ack(&curpacket, wf); // must ack here, because bridge mode prevents us from ack'ing
493 esp8266_wififlash_usb_bridge(); // this isn't quite right. we should only 'ack' once the bridge is ready
494 } else {
495 return 111;
496 }
497 return 0;
498}
499
500/**************************************************
501* \\brief process packets arriving on usb
502**************************************************/
503void usb_process_packet_appupdate() {
504 int i;
505
506 if (!packet_ready) {
507 return;
508 }
509 pctr = 0;
510 // this particular action may be out of order
511 if ((curpacket.type == 0x07) && (curpacket.action.action == 5)) {
512 usb_app_update_ack(&curpacket, 0);
513 reinit();
514 }
515
516 if (curpacket.number == 0) {
517 printf("[usbapp] Ignored pack 0\r\n");
518 packet_ready = 0; // clear it again
519 state = 0;
520 curpos = 0;
521 }
522
523 // check for out-of-order packets
524 if (curpacket.number != (lastpack + 1)) {
525#ifdef usb_app_debug
526 usbdebugf("[usbapp] Out of sequence. got %i, wanted %i\r\n", curpacket.number, (lastpack + 1));
527#endif
528 usb_app_update_nack(&curpacket, USBAPP_ERROR_PACKET_ORDER, ((curpacket.number << 16) | (lastpack + 1)));
529 packet_ready = 0; // clear it again
530 state = 0;
531 curpos = 0;
532 return;
533 }
534 lastpack = curpacket.number;
535#ifdef usb_app_debug
536 usbdebugf("[usbapp] Processing type %i\r\n", curpacket.type);
537#endif
538 /********************************* START UPLOAD *******************/
539 if (curpacket.type == 0x06) { // start_upload...
540 if (((uint32_t)get_app_header()) == curpacket.start_upload.base) {
541 started = 0;
542 usb_app_update_nack(&curpacket, USBAPP_ERROR_CURRENT_BASE, (uint32_t)get_app_header());
543 goto out;
544 }
545 printf("USB Flash. base: %p, length: %i\r\n", (void *)curpacket.start_upload.base, curpacket.start_upload.size);
546 baseaddr = (void *)curpacket.start_upload.base;
547 flash_flags = curpacket.start_upload.flags;
548 flash_app_init(baseaddr, flash_flags);
549 started = 1;
550 usb_app_update_ack(&curpacket, 0);
551 if (flash_flags & (1 << FLASH_FLAGS_PRE_ERASE)) {
552 preerase((void *)curpacket.start_upload.base, curpacket.start_upload.size);
553 }
554 /********************************* ACTION *******************/
555 } else if (curpacket.type == 0x07) { //action
556 uint32_t res;
557 int r = runaction(curpacket.action.action, curpacket.action.actiondata, &res);
558 if (r != 0) {
559 usb_app_update_nack(&curpacket, USBAPP_ERROR_ACTION, r);
560 goto out;
561 } else {
562#ifdef usb_app_debug
563 usbdebugf("[usbapp] Action result: %i\r\n", res);
564#endif
565 usb_app_update_ack(&curpacket, res);
566 }
567 /********************************* ACTION WITH DATA *******************/
568 } else if (curpacket.type == 0x08) { //action with data
569 uint32_t res;
570 int r = runaction_data(curpacket.action.action, curpacket.action.datalen, &res);
571 if (r != 0) {
572 usb_app_update_nack(&curpacket, USBAPP_ERROR_ACTION, r);
573 goto out;
574 } else {
575#ifdef usb_app_debug
576 usbdebugf("[usbapp] Action result: %i\r\n", res);
577#endif
578 usb_app_update_ack(&curpacket, res);
579 }
580 /********************************* FINISH *******************/
581 } else if (curpacket.type == 0x05) { // finish
582 total_size = curpacket.done.len;
583 // received enough data?
584 if (received != total_size) {
585#ifdef usb_app_debug
586 usbdebugf("[usbapp] ERROR: Received %i bytes, but advertised was %i\n", received, total_size);
587#endif
588 usb_app_update_nack(&curpacket, USBAPP_ERROR_TOTAL_SIZE_MISMATCH, received);
589 goto out;
590 }
591 // checksum?
592 uint32_t c = crc32(baseaddr, received);
593 if (c != curpacket.done.checksum) {
594#ifdef usb_app_debug
595 usbdebugf("[usbapp] ERROR: checksum calculated: 0x%X, reported: 0x%X\n", c, curpacket.done.checksum);
596#endif
597
598 usb_app_update_nack(&curpacket, USBAPP_ERROR_TOTAL_CHECKSUM, c);
599 goto out;
600 }
601 // all went well, ...
602 mculib_flash_lock(MAIN_MCULIBHANDLE);
603 usb_app_update_ack(&curpacket, 0);
604 /********************************* DATA *******************/
605 } else if (curpacket.type == 0x01) { // data
606 if (!started) {
607 usb_app_update_nack(&curpacket, USBAPP_ERROR_DATA_BEFORE_START, 0);
608 goto out;
609 }
610 if (curpacket.data.data_length != 512) {
611 usb_app_update_nack(&curpacket, USBAPP_ERROR_DATA_SIZE_INVALID, 512);
612 goto out;
613 }
614
615 // verify checksum
616 uint32_t c = crc32(usbbuf, curpacket.data.data_length);
617 if (c != curpacket.data.checksum) {
618#ifdef usb_app_debug
619 usbdebugf("[usbapp] checksum calculated: 0x%X, reported: 0x%X\n", c, curpacket.data.checksum);
620#endif
621
622 usb_app_update_nack(&curpacket, USBAPP_ERROR_DATA_CHECKSUM, c);
623 goto out;
624 }
625 i = flash_app_consumer(0, usbbuf, curpacket.data.data_length);
626 if (i != 0) {
627#ifdef usb_app_debug
628 usbdebugf("[usbapp] flash failed: %i\n", i);
629#endif
630 usb_app_update_nack(&curpacket, USBAPP_ERROR_FLASH_FAILURE, i);
631 goto out;
632 }
633 /*
634 * void *app = findAppAtBlock(baseaddr + received); // code intented to prevent accidental overwrite of app. not working
635 * usb_app_update_ack(&curpacket, (uint32_t)app);
636 */
637 usb_app_update_ack(&curpacket, 0);
638 received = received + curpacket.data.data_length;
639 /********************************* UNKNOWN PACKET *******************/
640 } else {
641#ifdef usb_app_debug
642 usbdebugf("[usbapp] Failed to process packet of type %i\n", curpacket.type);
643#endif
644 usb_app_update_nack(&curpacket, USBAPP_ERROR_INV_PACKET, curpacket.type);
645 }
646out:
647 packet_ready = 0; // clear it again
648 state = 0;
649 curpos = 0;
650}
651
652int usb_start_app_update() {
653 printf("[usbapp] Starting usb app update\r\n");
654 pctr = 0;
655 curpos = 0;
656 state = 0;
657 lastpack = 0;
658 received = 0;
659 timer_ts = 0;
660 usbbuf = mpm_reserve(1024);
661 if (usbbuf == NULL) {
662 printf("no usbbuf\r\n");
663 return 10;
664 }
665 mculib_usb_set_received_callback(MAIN_MCULIBHANDLE, usb_appupdate_byte_received);
666 print_to_usb(0);
667 printf(ready);
668 SENDTOUSB(strlen(ready), (byte *)ready);
669 return 0;
670}
671void usb_finish_app_update() {
672 usb_restore_irq();
673 print_to_usb(1);
674 mpm_free(usbbuf);
675 ringbuffer_init(&console_ringbuffer); // remove left-over stuff from usb buffer(s)
676 printf("[usbapp] finished usb app update\r\n");
677}
678
679/* called by main - return 0 on success, otherwise failure number */
680int usb_appupdate() {
681 unhijack_usb_acm();
682 power_set_speed(10);
683 int i = usb_start_app_update();
684
685 if (i != 0) {
686 return i;
687 }
688 int syncctr = 0;
689
690 pleasestop = 0;
691 for (;;) {
692 if (pleasestop) {
693 break;
694 }
695 if (mculib_has_time_passed(2, &timer_ts)) {
696 pctr++;
697 syncctr++;
698 if ((pctr >= 3) && (syncctr >= 3)) {
699 syncctr = 0;
700 sendsync();
701 }
702 if (pctr >= (MAX_SECS_USBFLASH / 2)) {
703 break;
704 }
705 }
706 avoid_watchdog();
707 usb_process_packet_appupdate();
708 }
709 flash_app_close(0, 0);
710 usb_finish_app_update();
711 return 0;
712}
713
714
715static void preerase(void *adr, uint32_t size) {
716 int r;
717
718 printf("Erasing %i bytes @ %p\r\n", size, adr);
719 mculib_flash_lock(MAIN_MCULIBHANDLE);
720 if ((r = mculib_flash_unlock(MAIN_MCULIBHANDLE))) {
721 printf("Flash unlock failed (%i)\r\n", r);
722 mculib_flash_lock(MAIN_MCULIBHANDLE);
723 return;
724 }
725 if ((r = mculib_flash_erase(MAIN_MCULIBHANDLE, adr, size))) {
726 printf("Flash erase failed (%i)\r\n", r);
727 }
728 mculib_flash_lock(MAIN_MCULIBHANDLE);
729 printf("Erase complete.\r\n");
730}
void * mpm_reserve(int bytes)
Definition: multiram.c:38
long get_my_node_id()
get the id of my node
void mpm_free(void *mem)
Definition: multiram.c:48
void esp8266_reset()
reset state machine and esp8266
Definition: esp8266.c:387
int flash_app_consumer(int fd, byte *b, int size)
called by stream whenever we got sufficient bytes (and only on full blocks!)
Definition: flashapp.c:102
void esp8266_add_ap(const char *ssid, const char *pw)
add an ap to the list of known ap
Definition: esp8266.c:424