From f0b4a32d6f983b1bece0b8cb2f2da1fdd23b012e Mon Sep 17 00:00:00 2001 From: Frank Gevaerts Date: Thu, 6 Mar 2008 21:25:09 +0000 Subject: reorganise the usb stack to provide a clean separation between core and class drivers git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16541 a1c6a512-1295-4272-9138-f99709370657 --- firmware/usbstack/usb_serial.c | 124 +++++++++++++++++++++++++++++------------ 1 file changed, 88 insertions(+), 36 deletions(-) (limited to 'firmware/usbstack/usb_serial.c') diff --git a/firmware/usbstack/usb_serial.c b/firmware/usbstack/usb_serial.c index 8c86932a31..55b76adc69 100644 --- a/firmware/usbstack/usb_serial.c +++ b/firmware/usbstack/usb_serial.c @@ -27,6 +27,31 @@ #ifdef USB_SERIAL +/* serial interface */ +struct usb_interface_descriptor __attribute__((aligned(2))) + interface_descriptor = +{ + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0 +}; + +struct usb_endpoint_descriptor __attribute__((aligned(2))) endpoint_descriptor = +{ + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0, + .bInterval = 0 +}; + #define BUFFER_SIZE 512 /* Max 16k because of controller limitations */ static unsigned char _send_buffer[BUFFER_SIZE] __attribute__((aligned(32))); static unsigned char* send_buffer; @@ -38,8 +63,66 @@ static int buffer_start; static int buffer_length; static bool active = false; +static int usb_endpoint; +static int usb_interface; + static struct mutex sendlock; +static void sendout(void) +{ + if(buffer_start+buffer_length > BUFFER_SIZE) + { + /* Buffer wraps. Only send the first part */ + usb_drv_send_nonblocking(usb_endpoint, &send_buffer[buffer_start], + (BUFFER_SIZE - buffer_start)); + } + else + { + /* Send everything */ + usb_drv_send_nonblocking(usb_endpoint, &send_buffer[buffer_start], + buffer_length); + } + busy_sending=true; +} + +int usb_serial_get_config_descriptor(unsigned char *dest,int max_packet_size, + int interface_number,int endpoint) +{ + endpoint_descriptor.wMaxPacketSize=max_packet_size; + interface_descriptor.bInterfaceNumber=interface_number; + + + memcpy(dest,&interface_descriptor,sizeof(struct usb_interface_descriptor)); + dest+=sizeof(struct usb_interface_descriptor); + + endpoint_descriptor.bEndpointAddress = endpoint | USB_DIR_IN, + memcpy(dest,&endpoint_descriptor,sizeof(struct usb_endpoint_descriptor)); + dest+=sizeof(struct usb_endpoint_descriptor); + + endpoint_descriptor.bEndpointAddress = endpoint | USB_DIR_OUT, + memcpy(dest,&endpoint_descriptor,sizeof(struct usb_endpoint_descriptor)); + return sizeof(struct usb_interface_descriptor) + + 2 * sizeof(struct usb_endpoint_descriptor); +} + +void usb_serial_init_connection(int interface,int endpoint) +{ + usb_interface = interface; + usb_endpoint = endpoint; + + /* prime rx endpoint */ + usb_drv_recv(usb_endpoint, receive_buffer, sizeof _receive_buffer); + + /* we come here too after a bus reset, so reset some data */ + mutex_lock(&sendlock); + busy_sending = false; + if(buffer_length>0) + { + sendout(); + } + mutex_unlock(&sendlock); +} + /* called by usb_code_init() */ void usb_serial_init(void) { @@ -53,26 +136,11 @@ void usb_serial_init(void) mutex_init(&sendlock); } -void usb_serial_exit(void) +void usb_serial_disconnect(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) @@ -85,13 +153,14 @@ void usb_serial_send(unsigned char *data,int length) /* 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,length); + memcpy(&send_buffer[(buffer_start+buffer_length)%BUFFER_SIZE], + data,length); buffer_length+=length; } else { /* current buffer doesn't wrap, so new data might */ - int available_end_space = (BUFFER_SIZE - (buffer_start + buffer_length)); + 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; @@ -121,7 +190,7 @@ void usb_serial_transfer_complete(bool in, int status, int length) case false: logf("serial: %s", receive_buffer); /* Data received. TODO : Do something with it ? */ - usb_drv_recv(EP_SERIAL, receive_buffer, sizeof _receive_buffer); + usb_drv_recv(usb_endpoint, receive_buffer, sizeof _receive_buffer); break; case true: @@ -148,26 +217,9 @@ bool usb_serial_control_request(struct usb_ctrlrequest* req) { bool handled = false; switch (req->bRequest) { - case USB_REQ_SET_CONFIGURATION: - logf("serial: set config"); - /* prime rx endpoint */ - usb_drv_recv(EP_SERIAL, receive_buffer, sizeof _receive_buffer); - handled = true; - - /* we come here too after a bus reset, so reset some data */ - mutex_lock(&sendlock); - busy_sending = false; - if(buffer_length>0) - { - sendout(); - } - mutex_unlock(&sendlock); - break; - default: logf("serial: unhandeld req %d", req->bRequest); } - return handled; } -- cgit v1.2.3