misc/usbdbg: Add CDC read/write callbacks.

These callbacks allow the debug code to read/write directly from
the stack, if possible, to avoid the extra memcpy.
This commit is contained in:
iabdalkader 2024-08-03 10:40:25 +03:00
parent 6b1308fcc5
commit f306d07b03
3 changed files with 151 additions and 146 deletions

View File

@ -20,12 +20,13 @@
#include "tusb.h" #include "tusb.h"
#include "usbdbg.h" #include "usbdbg.h"
#include "tinyusb_debug.h" #include "tinyusb_debug.h"
#include "omv_common.h"
#define DEBUG_MAX_PACKET (OMV_TUSBDBG_PACKET) #define DEBUG_BAUDRATE_SLOW (921600)
#define DEBUG_BAUDRATE_SLOW (921600) #define DEBUG_BAUDRATE_FAST (12000000)
#define DEBUG_BAUDRATE_FAST (12000000) #define DEBUG_EP_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
extern void __fatal_error(); void NORETURN __fatal_error(const char *msg);
typedef struct __attribute__((packed)) { typedef struct __attribute__((packed)) {
uint8_t cmd; uint8_t cmd;
@ -34,23 +35,23 @@ typedef struct __attribute__((packed)) {
} }
usbdbg_cmd_t; usbdbg_cmd_t;
static uint8_t debug_ringbuf_array[OMV_TUSBDBG_BUFFER]; static uint8_t tx_array[OMV_TUSBDBG_BUFFER];
static ringbuf_t tx_ringbuf = { tx_array, sizeof(tx_array) };
static volatile bool tinyusb_debug_mode = false; static volatile bool tinyusb_debug_mode = false;
ringbuf_t debug_ringbuf = { debug_ringbuf_array, sizeof(debug_ringbuf_array) };
uint32_t usb_cdc_buf_len() { uint32_t usb_cdc_buf_len() {
return ringbuf_avail(&debug_ringbuf); return ringbuf_avail(&tx_ringbuf);
} }
uint32_t usb_cdc_get_buf(uint8_t *buf, uint32_t len) { uint32_t usb_cdc_get_buf(uint8_t *buf, uint32_t len) {
// Read all of the request bytes. // Read all of the request bytes.
if (ringbuf_get_bytes(&debug_ringbuf, buf, len) == 0) { if (ringbuf_get_bytes(&tx_ringbuf, buf, len) == 0) {
return len; return len;
} }
// Try to read as much data as possible. // Try to read as much data as possible.
uint32_t bytes = 0; uint32_t bytes = 0;
for (; bytes < len; bytes++) { for (; bytes < len; bytes++) {
int c = ringbuf_get(&debug_ringbuf); int c = ringbuf_get(&tx_ringbuf);
if (c == -1) { if (c == -1) {
break; break;
} }
@ -59,9 +60,13 @@ uint32_t usb_cdc_get_buf(uint8_t *buf, uint32_t len) {
return bytes; return bytes;
} }
void usb_cdc_reset_buffers() {
}
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *coding) { void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *coding) {
debug_ringbuf.iget = 0; tx_ringbuf.iget = 0;
debug_ringbuf.iput = 0; tx_ringbuf.iput = 0;
if (0) { if (0) {
#if defined(MICROPY_BOARD_ENTER_BOOTLOADER) #if defined(MICROPY_BOARD_ENTER_BOOTLOADER)
@ -112,9 +117,9 @@ mp_uint_t __wrap_mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
// rate and fast print rate. When this happens, reset the buffer and start // rate and fast print rate. When this happens, reset the buffer and start
// over, if this string fits entirely in the buffer. This helps the ring buffer // over, if this string fits entirely in the buffer. This helps the ring buffer
// self-recover from broken strings. // self-recover from broken strings.
if (ringbuf_put(&debug_ringbuf, str[i]) == -1 && len <= debug_ringbuf.size) { if (ringbuf_put(&tx_ringbuf, str[i]) == -1 && len <= tx_ringbuf.size) {
debug_ringbuf.iget = 0; tx_ringbuf.iget = 0;
debug_ringbuf.iput = 0; tx_ringbuf.iput = 0;
} }
} }
NVIC_EnableIRQ(PendSV_IRQn); NVIC_EnableIRQ(PendSV_IRQn);
@ -132,20 +137,16 @@ static void tinyusb_debug_task(void) {
return; return;
} }
uint8_t dbg_buf[DEBUG_MAX_PACKET]; usbdbg_cmd_t cmd;
uint32_t count = tud_cdc_read(dbg_buf, 6); tud_cdc_read(&cmd, sizeof(cmd));
if (count < 6 || dbg_buf[0] != 0x30) { if (cmd.cmd != 0x30) {
// Maybe we should try to recover from this state // TODO: Try to recover from this state but for now, call __fatal_error.
// but for now, call __fatal_error which doesn't __fatal_error("Invalid USB CMD received.");
// return.
__fatal_error();
return;
} }
usbdbg_cmd_t *cmd = (usbdbg_cmd_t *) dbg_buf; uint8_t request = cmd.request;
uint8_t request = cmd->request; uint32_t xfer_length = cmd.xfer_length;
uint32_t xfer_length = cmd->xfer_length;
usbdbg_control(NULL, request, xfer_length); usbdbg_control(NULL, request, xfer_length);
while (xfer_length) { while (xfer_length) {
@ -155,19 +156,21 @@ static void tinyusb_debug_task(void) {
} }
if (request & 0x80) { if (request & 0x80) {
// Device-to-host data phase // Device-to-host data phase
int bytes = MIN(xfer_length, DEBUG_MAX_PACKET); int size = OMV_MIN(xfer_length, tud_cdc_write_available());
if (bytes <= tud_cdc_write_available()) { if (size) {
xfer_length -= bytes; xfer_length -= size;
usbdbg_data_in(dbg_buf, bytes); usbdbg_data_in(size, tud_cdc_write);
tud_cdc_write(dbg_buf, bytes); }
if (size > 0 && size < DEBUG_EP_SIZE) {
tud_cdc_write_flush();
} }
tud_cdc_write_flush();
} else { } else {
// Host-to-device data phase // Host-to-device data phase
int bytes = MIN(xfer_length, DEBUG_MAX_PACKET); int size = OMV_MIN(xfer_length, tud_cdc_available());
uint32_t count = tud_cdc_read(dbg_buf, bytes); if (size) {
xfer_length -= count; xfer_length -= size;
usbdbg_data_out(dbg_buf, count); usbdbg_data_out(size, tud_cdc_read);
}
} }
} }
} }

View File

@ -27,8 +27,8 @@
#include "omv_boardconfig.h" #include "omv_boardconfig.h"
#include "py_image.h" #include "py_image.h"
static int xfer_bytes; static int xfer_offs;
static int xfer_length; static int xfer_size;
static enum usbdbg_cmd cmd; static enum usbdbg_cmd cmd;
static volatile bool script_ready; static volatile bool script_ready;
@ -36,13 +36,11 @@ static volatile bool script_running;
static volatile bool irq_enabled; static volatile bool irq_enabled;
static vstr_t script_buf; static vstr_t script_buf;
// These functions must be implemented in MicroPython CDC driver. // These functions must be implemented by the stack.
extern uint32_t usb_cdc_buf_len(); extern uint32_t usb_cdc_buf_len();
extern uint32_t usb_cdc_get_buf(uint8_t *buf, uint32_t len); extern uint32_t usb_cdc_get_buf(uint8_t *buf, uint32_t len);
extern void usb_cdc_reset_buffers();
void __attribute__((weak)) usb_cdc_reset_buffers() {
}
void usbdbg_init() { void usbdbg_init() {
cmd = USBDBG_NONE; cmd = USBDBG_NONE;
@ -100,47 +98,54 @@ bool usbdbg_get_irq_enabled() {
return irq_enabled; return irq_enabled;
} }
void usbdbg_data_in(void *buffer, int length) { void usbdbg_data_in(uint32_t size, usbdbg_write_callback_t write_callback) {
switch (cmd) { switch (cmd) {
case USBDBG_FW_VERSION: { case USBDBG_FW_VERSION: {
uint32_t *ver_buf = buffer; uint32_t buffer[3] = {
ver_buf[0] = FIRMWARE_VERSION_MAJOR; FIRMWARE_VERSION_MAJOR,
ver_buf[1] = FIRMWARE_VERSION_MINOR; FIRMWARE_VERSION_MINOR,
ver_buf[2] = FIRMWARE_VERSION_PATCH; FIRMWARE_VERSION_PATCH,
};
cmd = USBDBG_NONE; cmd = USBDBG_NONE;
write_callback(&buffer, sizeof(buffer));
break; break;
} }
case USBDBG_TX_BUF_LEN: { case USBDBG_TX_BUF_LEN: {
uint32_t tx_buf_len = usb_cdc_buf_len(); uint32_t tx_buf_len = usb_cdc_buf_len();
memcpy(buffer, &tx_buf_len, sizeof(tx_buf_len));
cmd = USBDBG_NONE; cmd = USBDBG_NONE;
write_callback(&tx_buf_len, sizeof(tx_buf_len));
break; break;
} }
case USBDBG_SENSOR_ID: { case USBDBG_SENSOR_ID: {
int sensor_id = 0xFF; uint32_t buffer = 0xFF;
#if MICROPY_PY_SENSOR #if MICROPY_PY_SENSOR
if (sensor_is_detected() == true) { if (sensor_is_detected() == true) {
sensor_id = sensor_get_id(); buffer = sensor_get_id();
} }
#endif #endif
memcpy(buffer, &sensor_id, 4);
cmd = USBDBG_NONE; cmd = USBDBG_NONE;
write_callback(&buffer, sizeof(buffer));
break; break;
} }
case USBDBG_TX_BUF: { case USBDBG_TX_BUF: {
xfer_bytes += usb_cdc_get_buf(buffer, length); uint8_t buffer[size];
if (xfer_bytes == xfer_length) { size = usb_cdc_get_buf(buffer, size);
xfer_offs += size;
if (xfer_offs == xfer_size) {
cmd = USBDBG_NONE; cmd = USBDBG_NONE;
} }
if (size) {
write_callback(buffer, size);
}
break; break;
} }
case USBDBG_FRAME_SIZE: case USBDBG_FRAME_SIZE: {
// Return 0 if FB is locked or not ready. // Return 0 if FB is locked or not ready.
((uint32_t *) buffer)[0] = 0; uint32_t buffer[3] = { 0 };
// Try to lock FB. If header size == 0 frame is not ready // Try to lock FB. If header size == 0 frame is not ready
if (mutex_try_lock_alternate(&JPEG_FB()->lock, MUTEX_TID_IDE)) { if (mutex_try_lock_alternate(&JPEG_FB()->lock, MUTEX_TID_IDE)) {
// If header size == 0 frame is not ready // If header size == 0 frame is not ready
@ -149,19 +154,21 @@ void usbdbg_data_in(void *buffer, int length) {
mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_IDE); mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_IDE);
} else { } else {
// Return header w, h and size/bpp // Return header w, h and size/bpp
((uint32_t *) buffer)[0] = JPEG_FB()->w; buffer[0] = JPEG_FB()->w;
((uint32_t *) buffer)[1] = JPEG_FB()->h; buffer[1] = JPEG_FB()->h;
((uint32_t *) buffer)[2] = JPEG_FB()->size; buffer[2] = JPEG_FB()->size;
} }
} }
cmd = USBDBG_NONE; cmd = USBDBG_NONE;
write_callback(&buffer, sizeof(buffer));
break; break;
}
case USBDBG_FRAME_DUMP: case USBDBG_FRAME_DUMP:
if (xfer_bytes < xfer_length) { if (xfer_offs < xfer_size) {
memcpy(buffer, JPEG_FB()->pixels + xfer_bytes, length); write_callback(JPEG_FB()->pixels + xfer_offs, size);
xfer_bytes += length; xfer_offs += size;
if (xfer_bytes == xfer_length) { if (xfer_offs == xfer_size) {
cmd = USBDBG_NONE; cmd = USBDBG_NONE;
JPEG_FB()->w = 0; JPEG_FB()->h = 0; JPEG_FB()->size = 0; JPEG_FB()->w = 0; JPEG_FB()->h = 0; JPEG_FB()->size = 0;
mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_IDE); mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_IDE);
@ -170,6 +177,7 @@ void usbdbg_data_in(void *buffer, int length) {
break; break;
case USBDBG_ARCH_STR: { case USBDBG_ARCH_STR: {
uint8_t buffer[64];
unsigned int uid[3] = { unsigned int uid[3] = {
#if (OMV_BOARD_UID_SIZE == 2) #if (OMV_BOARD_UID_SIZE == 2)
0U, 0U,
@ -182,29 +190,29 @@ void usbdbg_data_in(void *buffer, int length) {
snprintf((char *) buffer, 64, "%s [%s:%08X%08X%08X]", snprintf((char *) buffer, 64, "%s [%s:%08X%08X%08X]",
OMV_BOARD_ARCH, OMV_BOARD_TYPE, uid[0], uid[1], uid[2]); OMV_BOARD_ARCH, OMV_BOARD_TYPE, uid[0], uid[1], uid[2]);
cmd = USBDBG_NONE; cmd = USBDBG_NONE;
write_callback(&buffer, sizeof(buffer));
break; break;
} }
case USBDBG_SCRIPT_RUNNING: { case USBDBG_SCRIPT_RUNNING: {
uint32_t *buf = buffer;
buf[0] = (uint32_t) script_running;
cmd = USBDBG_NONE; cmd = USBDBG_NONE;
uint32_t buffer = script_running;
write_callback(&buffer, sizeof(buffer));
break; break;
} }
case USBDBG_GET_STATE: case USBDBG_GET_STATE: {
// Clear flags uint32_t buffer[16] = { 0 };
((uint32_t *) buffer)[0] = 0;
// Set script running flag // Set script running flag
if (script_running) { if (script_running) {
((uint32_t *) buffer)[0] |= USBDBG_STATE_FLAGS_SCRIPT; buffer[0] |= USBDBG_STATE_FLAGS_SCRIPT;
} }
// Set text buf valid flag. // Set text buf valid flag.
uint32_t tx_buf_len = usb_cdc_buf_len(); uint32_t tx_buf_len = usb_cdc_buf_len();
if (tx_buf_len) { if (tx_buf_len) {
((uint32_t *) buffer)[0] |= USBDBG_STATE_FLAGS_TEXT; buffer[0] |= USBDBG_STATE_FLAGS_TEXT;
} }
// Try to lock FB. If header size == 0 frame is not ready // Try to lock FB. If header size == 0 frame is not ready
@ -214,13 +222,13 @@ void usbdbg_data_in(void *buffer, int length) {
// unlock FB // unlock FB
mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_IDE); mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_IDE);
} else { } else {
// Set frame width, height and size/bpp
((uint32_t *) buffer)[1] = JPEG_FB()->w;
((uint32_t *) buffer)[2] = JPEG_FB()->h;
((uint32_t *) buffer)[3] = JPEG_FB()->size;
// Set valid frame flag. // Set valid frame flag.
((uint32_t *) buffer)[0] |= USBDBG_STATE_FLAGS_FRAME; buffer[0] |= USBDBG_STATE_FLAGS_FRAME;
// Set frame width, height and size/bpp
buffer[1] = JPEG_FB()->w;
buffer[2] = JPEG_FB()->h;
buffer[3] = JPEG_FB()->size;
} }
} }
@ -233,19 +241,20 @@ void usbdbg_data_in(void *buffer, int length) {
} }
cmd = USBDBG_NONE; cmd = USBDBG_NONE;
write_callback(&buffer, sizeof(buffer));
break; break;
}
default: /* error */ default: /* error */
break; break;
} }
} }
void usbdbg_data_out(void *buffer, int length) { void usbdbg_data_out(uint32_t size, usbdbg_read_callback_t read_callback) {
switch (cmd) { switch (cmd) {
case USBDBG_FB_ENABLE: { case USBDBG_FB_ENABLE: {
uint32_t enable = *((int32_t *) buffer); read_callback(&(JPEG_FB()->enabled), 4);
JPEG_FB()->enabled = enable; if (JPEG_FB()->enabled == 0) {
if (enable == 0) {
// When disabling framebuffer, the IDE might still be holding FB lock. // When disabling framebuffer, the IDE might still be holding FB lock.
// If the IDE is not the current lock owner, this operation is ignored. // If the IDE is not the current lock owner, this operation is ignored.
mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_IDE); mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_IDE);
@ -256,16 +265,17 @@ void usbdbg_data_out(void *buffer, int length) {
case USBDBG_SCRIPT_EXEC: case USBDBG_SCRIPT_EXEC:
// check if GC is locked before allocating memory for vstr. If GC was locked // check if GC is locked before allocating memory for vstr. If GC was locked
// at least once before the script is fully uploaded xfer_bytes will be less // at least once before the script is fully uploaded xfer_offs will be less
// than the total length (xfer_length) and the script will Not be executed. // than the total size (xfer_size) and the script will Not be executed.
if (!script_running) { if (!script_running) {
nlr_buf_t nlr; nlr_buf_t nlr;
if (!gc_is_locked() && nlr_push(&nlr) == 0) { if (!gc_is_locked() && nlr_push(&nlr) == 0) {
vstr_add_strn(&script_buf, buffer, length); char *buffer = vstr_add_len(&script_buf, size);
read_callback(buffer, size);
nlr_pop(); nlr_pop();
} }
xfer_bytes += length; xfer_offs += size;
if (xfer_bytes == xfer_length) { if (xfer_offs == xfer_size) {
cmd = USBDBG_NONE; cmd = USBDBG_NONE;
// Schedule the IDE exception to interrupt the VM. // Schedule the IDE exception to interrupt the VM.
usbdbg_interrupt_vm(true); usbdbg_interrupt_vm(true);
@ -278,17 +288,15 @@ void usbdbg_data_out(void *buffer, int length) {
image_t image; image_t image;
framebuffer_init_image(&image); framebuffer_init_image(&image);
// null terminate the path size = MIN(128, size);
length = (length == 64) ? 63:length; char buffer[size];
((char *) buffer)[length] = 0; read_callback(buffer, size);
buffer[size - 1] = 0;
rectangle_t *roi = (rectangle_t *) buffer; rectangle_t *roi = (rectangle_t *) buffer;
char *path = (char *) buffer + sizeof(rectangle_t); char *path = (char *) buffer + sizeof(rectangle_t);
imlib_save_image(&image, path, roi, 50); imlib_save_image(&image, path, roi, 50);
// raise a flash IRQ to flush image
//NVIC->STIR = FLASH_IRQn;
#endif //IMLIB_ENABLE_IMAGE_FILE_IO #endif //IMLIB_ENABLE_IMAGE_FILE_IO
break; break;
} }
@ -299,9 +307,10 @@ void usbdbg_data_out(void *buffer, int length) {
image_t image; image_t image;
framebuffer_init_image(&image); framebuffer_init_image(&image);
// null terminate the path size = MIN(128, size);
length = (length == 64) ? 63:length; char buffer[size];
((char *) buffer)[length] = 0; read_callback(buffer, size);
buffer[size - 1] = 0;
rectangle_t *roi = (rectangle_t *) buffer; rectangle_t *roi = (rectangle_t *) buffer;
char *path = (char *) buffer + sizeof(rectangle_t); char *path = (char *) buffer + sizeof(rectangle_t);
@ -314,21 +323,24 @@ void usbdbg_data_out(void *buffer, int length) {
case USBDBG_ATTR_WRITE: { case USBDBG_ATTR_WRITE: {
#if MICROPY_PY_SENSOR #if MICROPY_PY_SENSOR
/* write sensor attribute */ struct {
int32_t attr = *((int32_t *) buffer); int32_t name;
int32_t val = *((int32_t *) buffer + 1); int32_t value;
switch (attr) { }
attr;
read_callback(&attr, sizeof(attr));
switch (attr.name) {
case ATTR_CONTRAST: case ATTR_CONTRAST:
sensor_set_contrast(val); sensor_set_contrast(attr.value);
break; break;
case ATTR_BRIGHTNESS: case ATTR_BRIGHTNESS:
sensor_set_brightness(val); sensor_set_brightness(attr.value);
break; break;
case ATTR_SATURATION: case ATTR_SATURATION:
sensor_set_saturation(val); sensor_set_saturation(attr.value);
break; break;
case ATTR_GAINCEILING: case ATTR_GAINCEILING:
sensor_set_gainceiling(val); sensor_set_gainceiling(attr.value);
break; break;
default: default:
break; break;
@ -340,61 +352,48 @@ void usbdbg_data_out(void *buffer, int length) {
case USBDBG_SET_TIME: { case USBDBG_SET_TIME: {
// TODO implement // TODO implement
#if 0 uint8_t buffer[32];
uint32_t *timebuf = (uint32_t *) buffer; read_callback(&buffer, sizeof(buffer));
timebuf[0]; // Year
timebuf[1]; // Month
timebuf[2]; // Day
timebuf[3]; // Day of the week
timebuf[4]; // Hour
timebuf[5]; // Minute
timebuf[6]; // Second
timebuf[7]; // Milliseconds
#endif
cmd = USBDBG_NONE; cmd = USBDBG_NONE;
break; break;
} }
case USBDBG_TX_INPUT: { case USBDBG_TX_INPUT: {
// TODO implement // TODO implement
#if 0
uint32_t key = *((uint32_t *) buffer);
#endif
cmd = USBDBG_NONE; cmd = USBDBG_NONE;
break; break;
} }
default: /* error */ default: /* error */
break; break;
} }
} }
void usbdbg_control(void *buffer, uint8_t request, uint32_t length) { void usbdbg_control(void *buffer, uint8_t request, uint32_t size) {
cmd = (enum usbdbg_cmd) request; cmd = (enum usbdbg_cmd) request;
switch (cmd) { switch (cmd) {
case USBDBG_FW_VERSION: case USBDBG_FW_VERSION:
xfer_bytes = 0; xfer_offs = 0;
xfer_length = length; xfer_size = size;
break; break;
case USBDBG_FRAME_SIZE: case USBDBG_FRAME_SIZE:
xfer_bytes = 0; xfer_offs = 0;
xfer_length = length; xfer_size = size;
break; break;
case USBDBG_FRAME_DUMP: case USBDBG_FRAME_DUMP:
xfer_bytes = 0; xfer_offs = 0;
xfer_length = length; xfer_size = size;
break; break;
case USBDBG_ARCH_STR: case USBDBG_ARCH_STR:
xfer_bytes = 0; xfer_offs = 0;
xfer_length = length; xfer_size = size;
break; break;
case USBDBG_SCRIPT_EXEC: case USBDBG_SCRIPT_EXEC:
xfer_bytes = 0; xfer_offs = 0;
xfer_length = length; xfer_size = size;
vstr_reset(&script_buf); vstr_reset(&script_buf);
break; break;
@ -415,20 +414,20 @@ void usbdbg_control(void *buffer, uint8_t request, uint32_t length) {
break; break;
case USBDBG_SCRIPT_RUNNING: case USBDBG_SCRIPT_RUNNING:
xfer_bytes = 0; xfer_offs = 0;
xfer_length = length; xfer_size = size;
break; break;
case USBDBG_TEMPLATE_SAVE: case USBDBG_TEMPLATE_SAVE:
case USBDBG_DESCRIPTOR_SAVE: case USBDBG_DESCRIPTOR_SAVE:
/* save template */ /* save template */
xfer_bytes = 0; xfer_offs = 0;
xfer_length = length; xfer_size = size;
break; break;
case USBDBG_ATTR_WRITE: case USBDBG_ATTR_WRITE:
xfer_bytes = 0; xfer_offs = 0;
xfer_length = length; xfer_size = size;
break; break;
case USBDBG_SYS_RESET: case USBDBG_SYS_RESET:
@ -449,35 +448,35 @@ void usbdbg_control(void *buffer, uint8_t request, uint32_t length) {
} }
case USBDBG_FB_ENABLE: { case USBDBG_FB_ENABLE: {
xfer_bytes = 0; xfer_offs = 0;
xfer_length = length; xfer_size = size;
break; break;
} }
case USBDBG_TX_BUF: case USBDBG_TX_BUF:
case USBDBG_TX_BUF_LEN: case USBDBG_TX_BUF_LEN:
xfer_bytes = 0; xfer_offs = 0;
xfer_length = length; xfer_size = size;
break; break;
case USBDBG_SENSOR_ID: case USBDBG_SENSOR_ID:
xfer_bytes = 0; xfer_offs = 0;
xfer_length = length; xfer_size = size;
break; break;
case USBDBG_SET_TIME: case USBDBG_SET_TIME:
xfer_bytes = 0; xfer_offs = 0;
xfer_length = length; xfer_size = size;
break; break;
case USBDBG_TX_INPUT: case USBDBG_TX_INPUT:
xfer_bytes = 0; xfer_offs = 0;
xfer_length = length; xfer_size = size;
break; break;
case USBDBG_GET_STATE: case USBDBG_GET_STATE:
xfer_bytes = 0; xfer_offs = 0;
xfer_length = length; xfer_size = size;
break; break;
default: /* error */ default: /* error */

View File

@ -58,6 +58,9 @@ enum usbdbg_state_flags {
USBDBG_STATE_FLAGS_FRAME = (1 << 2), USBDBG_STATE_FLAGS_FRAME = (1 << 2),
}; };
typedef uint32_t (*usbdbg_read_callback_t) (void *buf, uint32_t len);
typedef uint32_t (*usbdbg_write_callback_t) (const void *buf, uint32_t len);
void usbdbg_init(); void usbdbg_init();
void usbdbg_wait_for_command(uint32_t timeout); void usbdbg_wait_for_command(uint32_t timeout);
bool usbdbg_script_ready(); bool usbdbg_script_ready();
@ -66,8 +69,8 @@ bool usbdbg_is_busy();
bool usbdbg_get_irq_enabled(); bool usbdbg_get_irq_enabled();
void usbdbg_set_irq_enabled(bool enabled); void usbdbg_set_irq_enabled(bool enabled);
void usbdbg_set_script_running(bool running); void usbdbg_set_script_running(bool running);
void usbdbg_data_in(void *buffer, int length); void usbdbg_data_in(uint32_t size, usbdbg_write_callback_t write_callback);
void usbdbg_data_out(void *buffer, int length); void usbdbg_data_out(uint32_t size, usbdbg_read_callback_t read_callback);
void usbdbg_control(void *buffer, uint8_t brequest, uint32_t wlength); void usbdbg_control(void *buffer, uint8_t brequest, uint32_t wlength);
#endif /* __USBDBG_H__ */ #endif /* __USBDBG_H__ */