From fb5a321dd7c2848128b04b306f3e1e59c87a3f70 Mon Sep 17 00:00:00 2001 From: Stijn Kuipers Date: Thu, 29 Jun 2023 16:26:07 +0200 Subject: Initial Filedump Tadaaa!! --- sw/Core/Src/webusb.h | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100755 sw/Core/Src/webusb.h (limited to 'sw/Core/Src/webusb.h') diff --git a/sw/Core/Src/webusb.h b/sw/Core/Src/webusb.h new file mode 100755 index 0000000..3405de5 --- /dev/null +++ b/sw/Core/Src/webusb.h @@ -0,0 +1,162 @@ +#pragma once +#ifdef DEBUG +#define DEBUG_WU +#endif +#ifdef DEBUG_WU +#define WUDebugLog DebugLog +#else +#define WUDebugLog(...) +#endif + +#ifdef EMU +static inline uint32_t tud_vendor_write_available(void) { return 0; } +static inline uint32_t tud_vendor_available(void) { return 0; } +static inline uint32_t tud_vendor_read(void* buffer, uint32_t bufsize) { return 0; } +static inline uint32_t tud_vendor_write(const void* buffer, uint32_t bufsize) { return 0; } +#else +uint32_t tud_vendor_n_write_available (uint8_t itf); +uint32_t tud_vendor_n_available (uint8_t itf); +uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize); +uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); +static inline uint32_t tud_vendor_write_available (void) +{ + return tud_vendor_n_write_available(0); +} +static inline uint32_t tud_vendor_available (void) +{ + return tud_vendor_n_available(0); +} +static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize) +{ + return tud_vendor_n_read(0, buffer, bufsize); +} +static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize) +{ + return tud_vendor_n_write(0, buffer, bufsize); +} + +#endif +/* webusb wire format. 10 byte header, then data. +u32 magic = 0xf30fabca +u8 cmd // 0 = get, 1=set +u8 idx // 0 +u8 idx2 // 0 +u8 idx3 // 0 +u16 datalen // in bytes, not including this header, 0 for get, 1552 for set +*/ +typedef struct WebUSBHeader { // 10 byte header + u8 magic[4]; + u8 cmd,idx; + u16 offset; + u16 len; +} WebUSBHeader; +const static u8 wu_magic[4] = { 0xf3,0x0f,0xab,0xca }; // we expect magic to be these +#define WEB_USB_TIMEOUT 500 +enum { // state machine ticks thru these in order, more or less + WU_MAGIC0, + WU_MAGIC1, + WU_MAGIC2, + WU_MAGIC3, + WU_RECVHDR, + WU_RECVDATA, + WU_SENDHDR, + WU_SENDDATA, +}; +u8 wu_state = WU_MAGIC0; // current state +WebUSBHeader wu_hdr; // header of current command +u8* wu_data=(u8*)&wu_hdr; // buffer where we are reading/writing atm +int wu_len=1; // how much left to read/write before state transition +int wu_lasteventtime; // for timeout detection +void SetWUState(u8 state, u8* data, int len) { wu_state = state; wu_data = data; wu_len = len; } +void PumpWebUSB() { + while (1) { + if (millis() > wu_lasteventtime + WEB_USB_TIMEOUT) { // timeout! + reset: + SetWUState(WU_MAGIC0, wu_hdr.magic, 1); + } + int n; + if (wu_state < WU_SENDHDR) { // receive + //n = tud_vendor_available(); + //if (n<6) break; + n = tud_vendor_read(wu_data, wu_len); + } + else { // send + if (wu_len <= 0) { + // odd corner case. the state doesnt want to send anything. just pretend the state is done + goto statedone; + } + n = tud_vendor_write_available(); + if (n > wu_len) n = wu_len; + if (n <= 0) break; + n = tud_vendor_write(wu_data, n); + } + if (n <= 0) break; // nothing to do +#ifdef DEBUG_WU + WUDebugLog("%d (%d): ", wu_state,wu_len); + for (int i=0;i 0) break; // not done with this state yet. next time! + // ok! end of a state. whats next +statedone: + switch (wu_state) { + case WU_MAGIC0: case WU_MAGIC1: case WU_MAGIC2: case WU_MAGIC3: { + u8 m = wu_hdr.magic[wu_state]; + if (m != wu_magic[wu_state]) { + WUDebugLog("magic fail %02x %02x\r\n",m, wu_magic[wu_state]); + wu_hdr.magic[0] = m; + wu_len = 1; + wu_state = (m == wu_magic[0]) ? WU_MAGIC1 : WU_MAGIC0; // if we got the first byte, we can tick into next state! + wu_data = wu_hdr.magic + wu_state; + continue; + } + wu_state++; + wu_len = 1; + if (wu_state == WU_RECVHDR) { // time to get rest of header + WUDebugLog("get header!\r\n"); + wu_len = 10-4; + } + continue; } + case WU_RECVHDR: // ok we got the header. what do they want: + WUDebugLog("got header %d %d!\r\n", wu_hdr.cmd,wu_hdr.len); + if (wu_hdr.cmd > 1) goto reset; // invalid cmd? + if (wu_hdr.cmd == 0) { + // they asked to get a preset! + if (wu_hdr.len + wu_hdr.offset > sizeof(Preset) ) goto reset; + if (wu_hdr.offset >= sizeof(Preset)) goto reset; + if (wu_hdr.idx >= 32) wu_hdr.idx = sysparams.curpreset; + wu_hdr.cmd = 1; + if (wu_hdr.len == 0) + wu_hdr.len = sizeof(Preset) - wu_hdr.offset; + SetWUState(WU_SENDHDR, (u8*)&wu_hdr, 10); + } + else { + // they asked to set! + if (wu_hdr.len + wu_hdr.offset > sizeof(Preset) || wu_hdr.len<=0) goto reset; + if (wu_hdr.offset >= sizeof(Preset)) goto reset; + if (wu_hdr.idx >= 32) wu_hdr.idx = sysparams.curpreset; // idx>32, just use current + // switch to the specified preset ready to receive. + SetPreset(wu_hdr.idx, false); + SetWUState(WU_RECVDATA, ((u8*)&rampreset) + wu_hdr.offset, wu_hdr.len); + } + continue; + case WU_RECVDATA: + if (wu_hdr.cmd == 1) { + // finished receiving preset. mark it dirty + ramtime[GEN_PRESET] = millis(); + } + goto reset; + case WU_SENDHDR:// ok we sent them the header; now send them the data + { + u8* data = (wu_hdr.idx == sysparams.curpreset) ? (u8 * )&rampreset : (u8*)GetSavedPreset(wu_hdr.idx); + SetWUState(WU_SENDDATA, data + wu_hdr.offset, wu_hdr.len); + continue; + } + case WU_SENDDATA: // ok we finished sending our data. nothing to do except get ready for more. + goto reset; + } // state + } // while loop +} -- cgit v1.2.3