55 lines
2.7 KiB
C++
55 lines
2.7 KiB
C++
/* Shared SET USB boot dispatcher. The MCU wrapper supplies BOOT_* macros. */
|
|
#include "usb_setp_stream.h"
|
|
#include <string.h>
|
|
static setp_boot boot;
|
|
static bool reset_pending;
|
|
static uint32_t reset_at;
|
|
typedef struct { uint8_t *out; uint16_t size; uint32_t now; } reply_context;
|
|
void boot_protocol_init(void) { setp_boot_init(&boot,&BOOT_OPS,0,BOOT_APP_BASE,BOOT_APP_SIZE); }
|
|
void boot_protocol_poll(uint32_t now) {
|
|
if(reset_pending && (int32_t)(now-reset_at)>=0) BOOT_RESET();
|
|
}
|
|
static void dispatch(const setp_frame_t *r,void *user) {
|
|
reply_context *c=user;
|
|
uint8_t body[128]; uint16_t status=SETP_STATUS_OK; size_t n=0;
|
|
setp_frame_t response={0};
|
|
if((r->destination!=0 && r->destination!=BOOT_NODE) ||
|
|
(r->flags&(SETP_FLAG_RESPONSE|SETP_FLAG_EVENT))) return;
|
|
if(r->flags&(SETP_FLAG_ERROR|SETP_FLAG_MORE)) status=SETP_STATUS_INVALID_ARGUMENT;
|
|
else if(r->message_type>=SETP_MSG_FW_BEGIN && r->message_type<=SETP_MSG_FW_ACTIVATE) {
|
|
status=setp_boot_command(&boot,r->message_type,r->payload,r->payload_length);
|
|
if(!status && r->message_type==SETP_MSG_FW_STATUS)
|
|
n=setp_fw_status_encode(&boot.status,body+2,sizeof(body)-2);
|
|
if(!status && r->message_type==SETP_MSG_FW_ACTIVATE) {
|
|
reset_pending=true; reset_at=c->now+500;
|
|
}
|
|
} else if(r->payload_length) status=SETP_STATUS_INVALID_LENGTH;
|
|
else switch(r->message_type) {
|
|
case SETP_MSG_PING: setp_put_u32(body+2,c->now); n=4; break;
|
|
case SETP_MSG_DEVICE_INFO: {
|
|
static const uint8_t model[]=BOOT_MODEL;
|
|
const setp_device_info_t info={1,0,0,0x10000,3,0,sizeof(model)-1,model};
|
|
n=setp_device_info_encode(&info,body+2,sizeof(body)-2); break;
|
|
}
|
|
case SETP_MSG_CAPABILITIES: {
|
|
const setp_capabilities_t caps={1,SETP_MAX_PAYLOAD,
|
|
SETP_IFACE_MASK(SETP_IFACE_USB_CDC),SETP_FEATURE_FIRMWARE,0,0,0,0};
|
|
n=setp_capabilities_encode(&caps,body+2,sizeof(body)-2); break;
|
|
}
|
|
default: status=SETP_STATUS_UNSUPPORTED; break;
|
|
}
|
|
setp_put_u16(body,status); if(status) n=0;
|
|
response.flags=SETP_FLAG_RESPONSE|(status ? SETP_FLAG_ERROR : 0);
|
|
response.message_type=r->message_type; response.sequence=r->sequence;
|
|
response.source=BOOT_NODE; response.destination=r->source;
|
|
response.payload=body; response.payload_length=(uint16_t)(n+2);
|
|
c->size=(uint16_t)setp_frame_encode(&response,c->out,SETP_FRAME_MAX);
|
|
}
|
|
void usb_setp_reset(usb_setp_stream *s) { memset(s,0,sizeof(*s)); }
|
|
uint16_t usb_setp_feed(usb_setp_stream *s,uint8_t byte,uint32_t now,uint8_t *out) {
|
|
reply_context c={out,0,now};
|
|
if(now-s->last_byte>1000) setp_parser_reset(&s->parser);
|
|
s->last_byte=now; (void)setp_parser_feed(&s->parser,&byte,1,dispatch,&c);
|
|
return c.size;
|
|
}
|