1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
26 #include "usb_serial.h"
27 #include "usb_class_driver.h"
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,
42 .bInterfaceClass
= USB_CLASS_CDC_DATA
,
43 .bInterfaceSubClass
= 0,
44 .bInterfaceProtocol
= 0,
49 static struct usb_endpoint_descriptor
__attribute__((aligned(2)))
52 .bLength
= sizeof(struct usb_endpoint_descriptor
),
53 .bDescriptorType
= USB_DT_ENDPOINT
,
54 .bEndpointAddress
= 0,
55 .bmAttributes
= USB_ENDPOINT_XFER_BULK
,
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
);
84 ep_out
= usb_core_request_endpoint(USB_ENDPOINT_XFER_BULK
, USB_DIR_OUT
,
87 usb_core_release_endpoint(ep_in
);
94 int usb_serial_set_first_interface(int interface
)
96 usb_interface
= interface
;
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;
124 switch (req
->bRequest
) {
126 logf("serial: unhandeld req %d", req
->bRequest
);
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;
145 /* called by usb_code_init() */
146 void usb_serial_init(void)
148 logf("serial: init");
151 buffer_transitlength
= 0;
155 void usb_serial_disconnect(void)
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)
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
;
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
);
199 buffer_length
+=first_chunk
;
203 memcpy(&send_buffer
[0],&data
[first_chunk
],MIN(length
,buffer_start
));
204 buffer_length
+=MIN(length
,buffer_start
);
208 if (buffer_transitlength
==0)
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
)
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
);
229 /* Data sent out. Update circular buffer */
232 /* TODO: Handle (length != buffer_transitlength) */
234 buffer_start
=(buffer_start
+buffer_transitlength
)%BUFFER_SIZE
;
235 buffer_transitlength
= 0;
244 #endif /*USB_SERIAL*/