diff --git a/firmware/export/config.h b/firmware/export/config.h index 587da6c496..5fb260f336 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -1362,6 +1362,9 @@ Lyre prototype 1 */ //#define USB_HAS_INTERRUPT -- seems to be broken #endif /* CONFIG_USBOTG */ +#define USB_BATCH_NON_NATIVE +#define USB_BATCH_SLOTS 1 + /* define the class drivers to enable */ #ifdef BOOTLOADER diff --git a/firmware/export/usb_drv.h b/firmware/export/usb_drv.h index 76cba9d82b..6c8949200d 100644 --- a/firmware/export/usb_drv.h +++ b/firmware/export/usb_drv.h @@ -109,8 +109,6 @@ int usb_drv_deinit_endpoint(int endpoint); int usb_drv_get_frame_number(void); #endif -#if USB_BATCH_SLOTS > 0 - /* batched request api is for workloads that perform very high-frequency, * performance-sensitive isochronous transactions continuously. * this api allows multiple transaction requests to be buffered in udc driver. @@ -128,8 +126,6 @@ int usb_drv_batch_start(void); /* stop processing */ int usb_drv_batch_stop(void); -#endif - /* USB_STRING_INITIALIZER(u"Example String") */ #define USB_STRING_INITIALIZER(S) { \ sizeof(struct usb_string_descriptor) + sizeof(S) - sizeof(*S), \ diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c index 9d5fa04d13..9b90fbd5ad 100644 --- a/firmware/usbstack/usb_core.c +++ b/firmware/usbstack/usb_core.c @@ -554,6 +554,64 @@ void usb_core_hotswap_event(int volume, bool inserted) } #endif + +#ifdef USB_BATCH_NON_NATIVE +static uint8_t batch_ep = 0; +static bool batch_stopped; +static usb_drv_batch_get_more batch_get_more; + +int usb_drv_batch_init(int ep, usb_drv_batch_get_more get_more) +{ + if(batch_ep != 0) { + logf("usb_core: batch api in use user=0x%02X", batch_ep); + return -1; + } + batch_ep = ep; + batch_get_more = get_more; + batch_stopped = false; + return 0; +} + +int usb_drv_batch_deinit(void) +{ + logf("usb_core: batch deinit"); + usb_drv_batch_stop(); + batch_ep = 0; + return 0; +} + +static int batch_get_and_send(void) +{ + const void* ptr; + size_t len; + batch_get_more(&ptr, &len); + if(len == 0 || batch_stopped) { + return 0; + } + return usb_drv_send_nonblocking(EP_NUM(batch_ep), (void*)ptr, len); +} + +int usb_drv_batch_start(void) +{ + logf("usb_core: batch start"); + batch_stopped = false; + return batch_get_and_send(); +} + +int usb_drv_batch_stop(void) +{ + batch_stopped = true; + return 0; +} + +static void batch_xfer_complete(void) { + if(batch_stopped) { + return; + } + batch_get_and_send(); +} +#endif + static void usb_core_set_serial_function_id(void) { int i, id = 0; @@ -1130,8 +1188,14 @@ void usb_core_bus_reset(void) /* called by usb_drv_transfer_completed() */ void usb_core_transfer_complete(int endpoint, int dir, int status, int length) { - struct usb_transfer_completion_event_data* completion_event = - &ep_data[endpoint].completion_event[EP_DIR(dir)]; +#ifdef USB_BATCH_NON_NATIVE + /* batch api */ + if(batch_ep != 0 && (endpoint | dir) == batch_ep) { + batch_xfer_complete(); + return; + } +#endif + /* Fast notification */ fast_completion_handler_t handler = ep_data[endpoint].fast_completion_handler[EP_DIR(dir)]; if(handler != NULL && handler(endpoint, dir, status, length)) @@ -1154,6 +1218,9 @@ void usb_core_transfer_complete(int endpoint, int dir, int status, int length) } #endif + struct usb_transfer_completion_event_data* completion_event = + &ep_data[endpoint].completion_event[EP_DIR(dir)]; + completion_event->endpoint = endpoint; completion_event->dir = dir; completion_event->data[0] = data0;