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"
28 /*#define LOGF_ENABLE*/
31 /* serial interface */
32 static struct usb_interface_descriptor
__attribute__((aligned(2)))
33 interface_descriptor
=
35 .bLength
= sizeof(struct usb_interface_descriptor
),
36 .bDescriptorType
= USB_DT_INTERFACE
,
37 .bInterfaceNumber
= 0,
38 .bAlternateSetting
= 0,
40 .bInterfaceClass
= USB_CLASS_CDC_DATA
,
41 .bInterfaceSubClass
= 0,
42 .bInterfaceProtocol
= 0,
47 static struct usb_endpoint_descriptor
__attribute__((aligned(2)))
50 .bLength
= sizeof(struct usb_endpoint_descriptor
),
51 .bDescriptorType
= USB_DT_ENDPOINT
,
52 .bEndpointAddress
= 0,
53 .bmAttributes
= USB_ENDPOINT_XFER_BULK
,
58 #define BUFFER_SIZE 512
59 static unsigned char send_buffer
[BUFFER_SIZE
]
60 USB_DEVBSS_ATTR
__attribute__((aligned(32)));
61 static unsigned char receive_buffer
[32]
62 USB_DEVBSS_ATTR
__attribute__((aligned(32)));
64 static void sendout(void);
66 static int buffer_start
;
67 /* The number of bytes to transfer that haven't been given to the USB stack yet */
68 static int buffer_length
;
69 /* The number of bytes to transfer that have been given to the USB stack */
70 static int buffer_transitlength
;
71 static bool active
= false;
73 static int ep_in
, ep_out
;
74 static int usb_interface
;
76 int usb_serial_request_endpoints(struct usb_class_driver
*drv
)
78 ep_in
= usb_core_request_endpoint(USB_ENDPOINT_XFER_BULK
, USB_DIR_IN
, drv
);
82 ep_out
= usb_core_request_endpoint(USB_ENDPOINT_XFER_BULK
, USB_DIR_OUT
,
85 usb_core_release_endpoint(ep_in
);
92 int usb_serial_set_first_interface(int interface
)
94 usb_interface
= interface
;
98 int usb_serial_get_config_descriptor(unsigned char *dest
, int max_packet_size
)
100 unsigned char *orig_dest
= dest
;
102 interface_descriptor
.bInterfaceNumber
= usb_interface
;
103 PACK_DATA(dest
, interface_descriptor
);
105 endpoint_descriptor
.wMaxPacketSize
= max_packet_size
;
107 endpoint_descriptor
.bEndpointAddress
= ep_in
;
108 PACK_DATA(dest
, endpoint_descriptor
);
110 endpoint_descriptor
.bEndpointAddress
= ep_out
;
111 PACK_DATA(dest
, endpoint_descriptor
);
113 return (dest
- orig_dest
);
116 /* called by usb_core_control_request() */
117 bool usb_serial_control_request(struct usb_ctrlrequest
* req
, unsigned char* dest
)
119 bool handled
= false;
122 switch (req
->bRequest
) {
124 logf("serial: unhandeld req %d", req
->bRequest
);
129 void usb_serial_init_connection(void)
131 /* prime rx endpoint */
132 usb_drv_recv(ep_out
, receive_buffer
, sizeof receive_buffer
);
134 /* we come here too after a bus reset, so reset some data */
135 buffer_transitlength
= 0;
143 /* called by usb_code_init() */
144 void usb_serial_init(void)
146 logf("serial: init");
149 buffer_transitlength
= 0;
153 void usb_serial_disconnect(void)
158 static void sendout(void)
160 buffer_transitlength
= MIN(buffer_length
,BUFFER_SIZE
-buffer_start
);
161 /* For unknown reasons packets larger than 96 bytes are not sent. We play
162 * safe and limit to 32. TODO: find the real bug */
163 buffer_transitlength
= MIN(buffer_transitlength
,32);
164 if(buffer_transitlength
> 0)
166 buffer_length
-= buffer_transitlength
;
167 usb_drv_send_nonblocking(ep_in
, &send_buffer
[buffer_start
],
168 buffer_transitlength
);
172 void usb_serial_send(const unsigned char *data
,int length
)
174 int freestart
, available_end_space
, i
;
176 if (!active
||length
<=0)
179 i
=buffer_start
+buffer_length
+buffer_transitlength
;
180 freestart
=i
%BUFFER_SIZE
;
181 available_end_space
=BUFFER_SIZE
-i
;
183 if (0>=available_end_space
)
185 /* current buffer wraps, so new data can't wrap */
186 int available_space
= BUFFER_SIZE
-
187 (buffer_length
+ buffer_transitlength
);
189 length
= MIN(length
,available_space
);
190 memcpy(&send_buffer
[freestart
],data
,length
);
191 buffer_length
+=length
;
195 /* current buffer doesn't wrap, so new data might */
196 int first_chunk
= MIN(length
,available_end_space
);
198 memcpy(&send_buffer
[freestart
],data
,first_chunk
);
200 buffer_length
+=first_chunk
;
204 memcpy(&send_buffer
[0],&data
[first_chunk
],MIN(length
,buffer_start
));
205 buffer_length
+=MIN(length
,buffer_start
);
209 if (buffer_transitlength
==0)
211 /* else do nothing. The transfer completion handler will pick it up */
214 /* called by usb_core_transfer_complete() */
215 void usb_serial_transfer_complete(int ep
,int dir
, int status
, int length
)
222 logf("serial: %s", receive_buffer
);
223 /* Data received. TODO : Do something with it ? */
225 /* Get the next bit */
226 usb_drv_recv(ep_out
, receive_buffer
, sizeof receive_buffer
);
230 /* Data sent out. Update circular buffer */
233 /* TODO: Handle (length != buffer_transitlength) */
235 buffer_start
=(buffer_start
+buffer_transitlength
)%BUFFER_SIZE
;
236 buffer_transitlength
= 0;