From 776d015cc492cb9c682bb1d223011b7a808011e8 Mon Sep 17 00:00:00 2001 From: Frank Gevaerts Date: Sun, 2 Mar 2008 20:45:33 +0000 Subject: implement logf over usb-serial. Needs USB_SERIAL defined in usb_core.h to work, and needs to be enabled in the debug menu. It stops sending data after a while for unknown reasons. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16486 a1c6a512-1295-4272-9138-f99709370657 --- apps/debug_menu.c | 15 ++++++ firmware/logf.c | 10 ++++ firmware/usb.c | 2 - firmware/usbstack/usb_core.c | 14 ++++- firmware/usbstack/usb_serial.c | 119 +++++++++++++++++++++++++++++++++++------ firmware/usbstack/usb_serial.h | 3 ++ 6 files changed, 143 insertions(+), 20 deletions(-) diff --git a/apps/debug_menu.c b/apps/debug_menu.c index bb9a00c57b..f448d30b3c 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -2357,6 +2357,18 @@ static bool dbg_scrollwheel(void) } #endif +#if defined(HAVE_USBSTACK) && defined(ROCKBOX_HAS_LOGF) +extern bool usb_core_serial_enabled; + +static bool logf_usb_serial(void) +{ + usb_core_serial_enabled = !usb_core_serial_enabled; + gui_syncsplash(HZ, "USB logf %s", + usb_core_serial_enabled?"enabled":"disabled"); + return false; +} +#endif + /****** The menu *********/ struct the_menu_item { @@ -2436,6 +2448,9 @@ static const struct the_menu_item menuitems[] = { {"logf", logfdisplay }, {"logfdump", logfdump }, #endif +#if defined(HAVE_USBSTACK) && defined(ROCKBOX_HAS_LOGF) + {"logf over usb",logf_usb_serial }, +#endif #ifdef CPU_BOOST_LOGGING {"cpu_boost log",cpu_boost_log}, #endif diff --git a/firmware/logf.c b/firmware/logf.c index 2056db5cc4..da05a0a0c7 100644 --- a/firmware/logf.c +++ b/firmware/logf.c @@ -32,6 +32,11 @@ #include "logf.h" #include "serial.h" +#ifdef HAVE_USBSTACK +#include "usb_core.h" +#include "usbstack/usb_serial.h" +#endif + /* Only provide all this if asked to */ #ifdef ROCKBOX_HAS_LOGF @@ -107,6 +112,11 @@ void _logf(const char *format, ...) serial_tx(ptr); serial_tx("\r\n"); #endif +#ifdef USB_SERIAL + usb_serial_send(ptr,len); + usb_serial_send("\r\n",2); +#endif + va_end(ap); if(len < MAX_LOGF_ENTRY) /* pad with spaces up to the MAX_LOGF_ENTRY byte border */ diff --git a/firmware/usb.c b/firmware/usb.c index 5f6cffd5b2..529ecb773b 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -192,7 +192,6 @@ static void usb_thread(void) usb_state = USB_POWERED; #ifdef HAVE_USBSTACK usb_core_enable_protocol(USB_DRIVER_MASS_STORAGE,false); - usb_core_enable_protocol(USB_DRIVER_SERIAL,false);/* TODO: add debug setting */ usb_core_enable_protocol(USB_DRIVER_CHARGING_ONLY,true); usb_enable(true); #endif @@ -202,7 +201,6 @@ static void usb_thread(void) { #ifdef HAVE_USBSTACK usb_core_enable_protocol(USB_DRIVER_MASS_STORAGE,true); - usb_core_enable_protocol(USB_DRIVER_SERIAL,false);/* TODO: add debug setting */ usb_core_enable_protocol(USB_DRIVER_CHARGING_ONLY,false); usb_enable(true); #else diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c index 60a88e9490..218b297455 100644 --- a/firmware/usbstack/usb_core.c +++ b/firmware/usbstack/usb_core.c @@ -286,7 +286,8 @@ static bool initialized = false; static enum { DEFAULT, ADDRESS, CONFIGURED } usb_state; static bool usb_core_storage_enabled = false; -static bool usb_core_serial_enabled = false; +/* Next one is non-static, to enable setting it from the debug menu */ +bool usb_core_serial_enabled = false; static bool usb_core_charging_enabled = false; #if defined(USB_BENCHMARK) static bool usb_core_benchmark_enabled = false; @@ -405,6 +406,11 @@ void usb_core_init(void) void usb_core_exit(void) { +#ifdef USB_SERIAL + if(usb_core_serial_enabled) + usb_serial_exit(); +#endif + if (initialized) { usb_drv_exit(); } @@ -444,15 +450,21 @@ void usb_core_handle_transfer_completion(struct usb_transfer_completion_event_da void usb_core_enable_protocol(int driver,bool enabled) { switch(driver) { +#ifdef USB_STORAGE case USB_DRIVER_MASS_STORAGE: usb_core_storage_enabled = enabled; break; +#endif +#ifdef USB_SERIAL case USB_DRIVER_SERIAL: usb_core_serial_enabled = enabled; break; +#endif +#ifdef USB_CHARGING_ONLY case USB_DRIVER_CHARGING_ONLY: usb_core_charging_enabled = enabled; break; +#endif } } diff --git a/firmware/usbstack/usb_serial.c b/firmware/usbstack/usb_serial.c index 77878092d7..5aca36b59a 100644 --- a/firmware/usbstack/usb_serial.c +++ b/firmware/usbstack/usb_serial.c @@ -16,46 +16,127 @@ * KIND, either express or implied. * ****************************************************************************/ +#include "string.h" #include "system.h" #include "usb_core.h" #include "usb_drv.h" +#include "kernel.h" //#define LOGF_ENABLE #include "logf.h" #ifdef USB_SERIAL -static unsigned char _transfer_buffer[16]; -static unsigned char* transfer_buffer; +#define BUFFER_SIZE 16384 /* No larger, because of controller limitations */ +static unsigned char _send_buffer[BUFFER_SIZE] __attribute__((aligned(32))); +static unsigned char* send_buffer; + +static unsigned char _receive_buffer[512] __attribute__((aligned(32))); +static unsigned char* receive_buffer; +static bool busy_sending = false; +static int buffer_start; +static int buffer_length; +static bool active = false; + +static struct mutex sendlock; /* called by usb_code_init() */ void usb_serial_init(void) { logf("serial: init"); - transfer_buffer = (void*)UNCACHED_ADDR(&_transfer_buffer); + send_buffer = (void*)UNCACHED_ADDR(&_send_buffer); + receive_buffer = (void*)UNCACHED_ADDR(&_receive_buffer); + busy_sending = false; + buffer_start = 0; + buffer_length = 0; + active = true; + mutex_init(&sendlock); +} + +void usb_serial_exit(void) +{ + active = false; +} + +static void sendout(void) +{ + if(buffer_start+buffer_length > BUFFER_SIZE) + { + /* Buffer wraps. Only send the first part */ + usb_drv_send_nonblocking(EP_SERIAL, &send_buffer[buffer_start],(BUFFER_SIZE - buffer_start)); + } + else + { + /* Send everything */ + usb_drv_send_nonblocking(EP_SERIAL, &send_buffer[buffer_start],buffer_length); + } + busy_sending=true; +} + +void usb_serial_send(unsigned char *data,int length) +{ + if(!active) + return; + mutex_lock(&sendlock); + if(buffer_start+buffer_length > BUFFER_SIZE) + { + /* current buffer wraps, so new data can't */ + int available_space = BUFFER_SIZE - buffer_length; + length=MIN(length,available_space); + memcpy(&send_buffer[(buffer_start+buffer_length)%BUFFER_SIZE],data,MIN(length,available_space)); + buffer_length+=length; + } + else + { + /* current buffer doesn't wrap, so new data might */ + int available_end_space = (BUFFER_SIZE - (buffer_start + buffer_length)); + int first_chunk = MIN(length,available_end_space); + memcpy(&send_buffer[buffer_start + buffer_length],data,first_chunk); + length-=first_chunk; + buffer_length+=first_chunk; + if(length>0) + { + /* wrap */ + memcpy(&send_buffer[0],&data[first_chunk],MIN(length,buffer_start)); + buffer_length+=MIN(length,buffer_start); + } + } + if(busy_sending) + { + /* Do nothing. The transfer completion handler will pick it up */ + } + else + { + sendout(); + } + mutex_unlock(&sendlock); } /* called by usb_core_transfer_complete() */ void usb_serial_transfer_complete(bool in, int status, int length) { - int i; switch (in) { case false: - logf("serial: %s", transfer_buffer); - /* Data received. Send it back */ - for(i=0;i0x40 && transfer_buffer[i]<0x5b) - transfer_buffer[i]+=0x20; - else if(transfer_buffer[i]>0x60 && transfer_buffer[i]<0x7b) - transfer_buffer[i]-=0x20; - } - usb_drv_send_nonblocking(EP_SERIAL, transfer_buffer, length); + logf("serial: %s", receive_buffer); + /* Data received. TODO : Do something with it ? */ + usb_drv_recv(EP_SERIAL, receive_buffer, sizeof _receive_buffer); break; case true: - /* Data sent out (maybe correctly, but we don't actually care. - * Re-prime read endpoint */ - usb_drv_recv(EP_SERIAL, transfer_buffer, sizeof _transfer_buffer); + mutex_lock(&sendlock); + /* Data sent out. Update circular buffer */ + if(status == 0) + { + buffer_start = (buffer_start + length)%BUFFER_SIZE; + buffer_length -= length; + } + busy_sending = false; + + if(buffer_length!=0) + { + sendout(); + } + mutex_unlock(&sendlock); break; } } @@ -68,8 +149,12 @@ bool usb_serial_control_request(struct usb_ctrlrequest* req) case USB_REQ_SET_CONFIGURATION: logf("serial: set config"); /* prime rx endpoint */ - usb_drv_recv(EP_SERIAL, transfer_buffer, sizeof _transfer_buffer); + usb_drv_recv(EP_SERIAL, receive_buffer, sizeof _receive_buffer); handled = true; + + /* we come here too after a bus reset, so reset some data */ + busy_sending = false; + sendout(); break; default: diff --git a/firmware/usbstack/usb_serial.h b/firmware/usbstack/usb_serial.h index 60cede9bda..bcb0648af5 100644 --- a/firmware/usbstack/usb_serial.h +++ b/firmware/usbstack/usb_serial.h @@ -22,8 +22,11 @@ #include "usb_ch9.h" void usb_serial_init(void); +void usb_serial_exit(void); void usb_serial_transfer_complete(bool in, int status, int length); bool usb_serial_control_request(struct usb_ctrlrequest* req); +void usb_serial_send(unsigned char *data,int length); + #endif -- cgit v1.2.3