Use a struct for the necessary status variables for rockblox. Will make dumping the...
[kugel-rb.git] / firmware / usbstack / usb_serial.c
blob246938a1ef1f97d7f4bee8c3e404a1f58fd5b5fa
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 by Christian Gmeiner
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "string.h"
22 #include "system.h"
23 #include "usb_core.h"
24 #include "usb_drv.h"
25 #include "kernel.h"
26 #include "usb_serial.h"
27 #include "usb_class_driver.h"
28 //#define LOGF_ENABLE
29 #include "logf.h"
31 #ifdef USB_SERIAL
33 /* serial interface */
34 static struct usb_interface_descriptor __attribute__((aligned(2)))
35 interface_descriptor =
37 .bLength = sizeof(struct usb_interface_descriptor),
38 .bDescriptorType = USB_DT_INTERFACE,
39 .bInterfaceNumber = 0,
40 .bAlternateSetting = 0,
41 .bNumEndpoints = 2,
42 .bInterfaceClass = USB_CLASS_CDC_DATA,
43 .bInterfaceSubClass = 0,
44 .bInterfaceProtocol = 0,
45 .iInterface = 0
49 static struct usb_endpoint_descriptor __attribute__((aligned(2)))
50 endpoint_descriptor =
52 .bLength = sizeof(struct usb_endpoint_descriptor),
53 .bDescriptorType = USB_DT_ENDPOINT,
54 .bEndpointAddress = 0,
55 .bmAttributes = USB_ENDPOINT_XFER_BULK,
56 .wMaxPacketSize = 0,
57 .bInterval = 0
60 #define BUFFER_SIZE 512
61 static unsigned char send_buffer[BUFFER_SIZE]
62 USB_DEVBSS_ATTR __attribute__((aligned(32)));
63 static unsigned char receive_buffer[32]
64 USB_DEVBSS_ATTR __attribute__((aligned(32)));
66 static void sendout(void);
68 static int buffer_start;
69 /* The number of bytes to transfer that haven't been given to the USB stack yet */
70 static int buffer_length;
71 /* The number of bytes to transfer that have been given to the USB stack */
72 static int buffer_transitlength;
73 static bool active = false;
75 static int ep_in, ep_out;
76 static int usb_interface;
78 int usb_serial_request_endpoints(struct usb_class_driver *drv)
80 ep_in = usb_core_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_IN, drv);
81 if (ep_in < 0)
82 return -1;
84 ep_out = usb_core_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_OUT,
85 drv);
86 if (ep_out < 0) {
87 usb_core_release_endpoint(ep_in);
88 return -1;
91 return 0;
94 int usb_serial_set_first_interface(int interface)
96 usb_interface = interface;
97 return interface + 1;
100 int usb_serial_get_config_descriptor(unsigned char *dest, int max_packet_size)
102 unsigned char *orig_dest = dest;
104 interface_descriptor.bInterfaceNumber = usb_interface;
105 PACK_DATA(dest, interface_descriptor);
107 endpoint_descriptor.wMaxPacketSize = max_packet_size;
109 endpoint_descriptor.bEndpointAddress = ep_in;
110 PACK_DATA(dest, endpoint_descriptor);
112 endpoint_descriptor.bEndpointAddress = ep_out;
113 PACK_DATA(dest, endpoint_descriptor);
115 return (dest - orig_dest);
118 /* called by usb_core_control_request() */
119 bool usb_serial_control_request(struct usb_ctrlrequest* req, unsigned char* dest)
121 bool handled = false;
123 (void)dest;
124 switch (req->bRequest) {
125 default:
126 logf("serial: unhandeld req %d", req->bRequest);
128 return handled;
131 void usb_serial_init_connection(void)
133 /* prime rx endpoint */
134 usb_drv_recv(ep_out, receive_buffer, sizeof receive_buffer);
136 /* we come here too after a bus reset, so reset some data */
137 buffer_transitlength = 0;
138 if(buffer_length>0)
140 sendout();
142 active=true;
145 /* called by usb_code_init() */
146 void usb_serial_init(void)
148 logf("serial: init");
149 buffer_start = 0;
150 buffer_length = 0;
151 buffer_transitlength = 0;
152 active = true;
155 void usb_serial_disconnect(void)
157 active = false;
160 static void sendout(void)
162 buffer_transitlength = MIN(buffer_length,BUFFER_SIZE-buffer_start);
163 if(buffer_transitlength > 0)
165 buffer_length -= buffer_transitlength;
166 usb_drv_send_nonblocking(ep_in, &send_buffer[buffer_start],
167 buffer_transitlength);
171 void usb_serial_send(unsigned char *data,int length)
173 int freestart, available_end_space, i;
175 if (!active||length<=0)
176 return;
178 i=buffer_start+buffer_length+buffer_transitlength;
179 freestart=i%BUFFER_SIZE;
180 available_end_space=BUFFER_SIZE-i;
182 if (0>=available_end_space)
184 /* current buffer wraps, so new data can't wrap */
185 int available_space = BUFFER_SIZE -
186 (buffer_length + buffer_transitlength);
188 length = MIN(length,available_space);
189 memcpy(&send_buffer[freestart],data,length);
190 buffer_length+=length;
192 else
194 /* current buffer doesn't wrap, so new data might */
195 int first_chunk = MIN(length,available_end_space);
197 memcpy(&send_buffer[freestart],data,first_chunk);
198 length-=first_chunk;
199 buffer_length+=first_chunk;
200 if(length>0)
202 /* wrap */
203 memcpy(&send_buffer[0],&data[first_chunk],MIN(length,buffer_start));
204 buffer_length+=MIN(length,buffer_start);
208 if (buffer_transitlength==0)
209 sendout();
210 /* else do nothing. The transfer completion handler will pick it up */
213 /* called by usb_core_transfer_complete() */
214 void usb_serial_transfer_complete(int ep,int dir, int status, int length)
216 (void)ep;
217 (void)length;
219 switch (dir) {
220 case USB_DIR_OUT:
221 logf("serial: %s", receive_buffer);
222 /* Data received. TODO : Do something with it ? */
224 /* Get the next bit */
225 usb_drv_recv(ep_out, receive_buffer, sizeof receive_buffer);
226 break;
228 case USB_DIR_IN:
229 /* Data sent out. Update circular buffer */
230 if(status == 0)
232 /* TODO: Handle (length != buffer_transitlength) */
234 buffer_start=(buffer_start+buffer_transitlength)%BUFFER_SIZE;
235 buffer_transitlength = 0;
238 if(buffer_length>0)
239 sendout();
240 break;
244 #endif /*USB_SERIAL*/