Use more formal English (passive)
[kugel-rb.git] / firmware / usbstack / usb_serial.c
blobb7d50622371845200b15add2de04e4f5b33efcba
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"
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))) endpoint_descriptor =
51 .bLength = sizeof(struct usb_endpoint_descriptor),
52 .bDescriptorType = USB_DT_ENDPOINT,
53 .bEndpointAddress = 0,
54 .bmAttributes = USB_ENDPOINT_XFER_BULK,
55 .wMaxPacketSize = 0,
56 .bInterval = 0
59 #define BUFFER_SIZE 512
60 static unsigned char send_buffer[BUFFER_SIZE]
61 USB_DEVBSS_ATTR __attribute__((aligned(32)));
62 static unsigned char receive_buffer[32]
63 USB_DEVBSS_ATTR __attribute__((aligned(32)));
65 static void sendout(void);
67 static int buffer_start;
68 /* The number of bytes to transfer that haven't been given to the USB stack yet */
69 static int buffer_length;
70 /* The number of bytes to transfer that have been given to the USB stack */
71 static int buffer_transitlength;
72 static bool active = false;
74 static int ep_in, ep_out;
75 static int usb_interface;
77 int usb_serial_request_endpoints(struct usb_class_driver *drv)
79 ep_in = usb_core_request_endpoint(USB_DIR_IN, drv);
81 if (ep_in < 0)
82 return -1;
84 ep_out = usb_core_request_endpoint(USB_DIR_OUT, 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;
101 int usb_serial_get_config_descriptor(unsigned char *dest,int max_packet_size)
103 unsigned char *orig_dest = dest;
105 endpoint_descriptor.wMaxPacketSize=max_packet_size;
106 interface_descriptor.bInterfaceNumber=usb_interface;
108 memcpy(dest,&interface_descriptor,sizeof(struct usb_interface_descriptor));
109 dest+=sizeof(struct usb_interface_descriptor);
111 endpoint_descriptor.bEndpointAddress = ep_in;
112 memcpy(dest,&endpoint_descriptor,sizeof(struct usb_endpoint_descriptor));
113 dest+=sizeof(struct usb_endpoint_descriptor);
115 endpoint_descriptor.bEndpointAddress = ep_out;
116 memcpy(dest,&endpoint_descriptor,sizeof(struct usb_endpoint_descriptor));
117 dest+=sizeof(struct usb_endpoint_descriptor);
119 return (dest - orig_dest);
122 /* called by usb_core_control_request() */
123 bool usb_serial_control_request(struct usb_ctrlrequest* req)
125 bool handled = false;
126 switch (req->bRequest) {
127 default:
128 logf("serial: unhandeld req %d", req->bRequest);
130 return handled;
133 void usb_serial_init_connection(void)
135 /* prime rx endpoint */
136 usb_drv_recv(ep_out, receive_buffer, sizeof receive_buffer);
138 /* we come here too after a bus reset, so reset some data */
139 buffer_transitlength = 0;
140 if(buffer_length>0)
142 sendout();
144 active=true;
147 /* called by usb_code_init() */
148 void usb_serial_init(void)
150 logf("serial: init");
151 buffer_start = 0;
152 buffer_length = 0;
153 buffer_transitlength = 0;
154 active = true;
157 void usb_serial_disconnect(void)
159 active = false;
162 static void sendout(void)
164 if(buffer_start+buffer_length >= BUFFER_SIZE)
166 /* Buffer wraps. Only send the first part */
167 buffer_transitlength=BUFFER_SIZE - buffer_start;
169 else
171 /* Send everything */
172 buffer_transitlength=buffer_length;
174 if(buffer_transitlength>0)
176 buffer_length-=buffer_transitlength;
177 usb_drv_send_nonblocking(ep_in, &send_buffer[buffer_start],
178 buffer_transitlength);
182 void usb_serial_send(unsigned char *data,int length)
184 if(!active)
185 return;
186 if(length<=0)
187 return;
188 int freestart=(buffer_start+buffer_length+buffer_transitlength)%BUFFER_SIZE;
189 if(buffer_start+buffer_transitlength+buffer_length >= BUFFER_SIZE)
191 /* current buffer wraps, so new data can't */
192 int available_space = BUFFER_SIZE - buffer_length - buffer_transitlength;
193 length=MIN(length,available_space);
194 memcpy(&send_buffer[freestart],
195 data,length);
196 buffer_length+=length;
198 else
200 /* current buffer doesn't wrap, so new data might */
201 int available_end_space = (BUFFER_SIZE - (buffer_start+buffer_length+buffer_transitlength));
202 int first_chunk = MIN(length,available_end_space);
203 memcpy(&send_buffer[freestart],data,first_chunk);
204 length-=first_chunk;
205 buffer_length+=first_chunk;
206 if(length>0)
208 /* wrap */
209 memcpy(&send_buffer[0],&data[first_chunk],MIN(length,buffer_start));
210 buffer_length+=MIN(length,buffer_start);
213 if(buffer_transitlength>0)
215 /* Do nothing. The transfer completion handler will pick it up */
217 else
219 sendout();
223 /* called by usb_core_transfer_complete() */
224 void usb_serial_transfer_complete(int ep,int dir, int status, int length)
226 (void)ep;
227 switch (dir) {
228 case USB_DIR_OUT:
229 logf("serial: %s", receive_buffer);
230 /* Data received. TODO : Do something with it ? */
232 /* Get the next bit */
233 usb_drv_recv(ep_out, receive_buffer, sizeof receive_buffer);
234 break;
236 case USB_DIR_IN:
237 /* Data sent out. Update circular buffer */
238 if(status == 0)
240 if(length!=buffer_transitlength)
242 /* do something? */
244 buffer_start = (buffer_start + buffer_transitlength)%BUFFER_SIZE;
245 buffer_transitlength = 0;
248 if(buffer_length>0)
250 sendout();
252 break;
257 #endif /*USB_SERIAL*/