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"
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))) endpoint_descriptor
=
51 .bLength
= sizeof(struct usb_endpoint_descriptor
),
52 .bDescriptorType
= USB_DT_ENDPOINT
,
53 .bEndpointAddress
= 0,
54 .bmAttributes
= USB_ENDPOINT_XFER_BULK
,
59 #define BUFFER_SIZE 512 /* Max 16k because of controller limitations */
60 #if CONFIG_CPU == IMX31L
61 static unsigned char send_buffer
[BUFFER_SIZE
]
62 USBDEVBSS_ATTR
__attribute__((aligned(32)));
63 static unsigned char receive_buffer
[32]
64 USBDEVBSS_ATTR
__attribute__((aligned(32)));
66 static unsigned char send_buffer
[BUFFER_SIZE
] __attribute__((aligned(32)));
67 static unsigned char receive_buffer
[32] __attribute__((aligned(32)));
70 static bool busy_sending
= false;
71 static int buffer_start
;
72 static int buffer_length
;
73 static bool active
= false;
75 static int ep_in
, ep_out
;
76 static int usb_interface
;
78 static struct mutex sendlock SHAREDBSS_ATTR
;
80 static void sendout(void)
82 if(buffer_start
+buffer_length
> BUFFER_SIZE
)
84 /* Buffer wraps. Only send the first part */
85 usb_drv_send_nonblocking(ep_in
, &send_buffer
[buffer_start
],
86 (BUFFER_SIZE
- buffer_start
));
91 usb_drv_send_nonblocking(ep_in
, &send_buffer
[buffer_start
],
97 int usb_serial_request_endpoints(struct usb_class_driver
*drv
)
99 ep_in
= usb_core_request_endpoint(USB_DIR_IN
, drv
);
104 ep_out
= usb_core_request_endpoint(USB_DIR_OUT
, drv
);
107 usb_core_release_endpoint(ep_in
);
114 int usb_serial_set_first_interface(int interface
)
116 usb_interface
= interface
;
117 return interface
+ 1;
121 int usb_serial_get_config_descriptor(unsigned char *dest
,int max_packet_size
)
123 unsigned char *orig_dest
= dest
;
125 endpoint_descriptor
.wMaxPacketSize
=max_packet_size
;
126 interface_descriptor
.bInterfaceNumber
=usb_interface
;
128 memcpy(dest
,&interface_descriptor
,sizeof(struct usb_interface_descriptor
));
129 dest
+=sizeof(struct usb_interface_descriptor
);
131 endpoint_descriptor
.bEndpointAddress
= ep_in
;
132 memcpy(dest
,&endpoint_descriptor
,sizeof(struct usb_endpoint_descriptor
));
133 dest
+=sizeof(struct usb_endpoint_descriptor
);
135 endpoint_descriptor
.bEndpointAddress
= ep_out
;
136 memcpy(dest
,&endpoint_descriptor
,sizeof(struct usb_endpoint_descriptor
));
137 dest
+=sizeof(struct usb_endpoint_descriptor
);
139 return (dest
- orig_dest
);
142 void usb_serial_init_connection(void)
144 /* prime rx endpoint */
145 usb_drv_recv(ep_out
, receive_buffer
, sizeof receive_buffer
);
147 /* we come here too after a bus reset, so reset some data */
148 mutex_lock(&sendlock
);
149 busy_sending
= false;
154 mutex_unlock(&sendlock
);
157 /* called by usb_code_init() */
158 void usb_serial_init(void)
160 logf("serial: init");
161 busy_sending
= false;
165 mutex_init(&sendlock
);
168 void usb_serial_disconnect(void)
173 void usb_serial_send(unsigned char *data
,int length
)
179 mutex_lock(&sendlock
);
180 if(buffer_start
+buffer_length
> BUFFER_SIZE
)
182 /* current buffer wraps, so new data can't */
183 int available_space
= BUFFER_SIZE
- buffer_length
;
184 length
=MIN(length
,available_space
);
185 memcpy(&send_buffer
[(buffer_start
+buffer_length
)%BUFFER_SIZE
],
187 buffer_length
+=length
;
191 /* current buffer doesn't wrap, so new data might */
192 int available_end_space
= (BUFFER_SIZE
- (buffer_start
+buffer_length
));
193 int first_chunk
= MIN(length
,available_end_space
);
194 memcpy(&send_buffer
[buffer_start
+ buffer_length
],data
,first_chunk
);
196 buffer_length
+=first_chunk
;
200 memcpy(&send_buffer
[0],&data
[first_chunk
],MIN(length
,buffer_start
));
201 buffer_length
+=MIN(length
,buffer_start
);
206 /* Do nothing. The transfer completion handler will pick it up */
212 mutex_unlock(&sendlock
);
215 /* called by usb_core_transfer_complete() */
216 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 ? */
223 usb_drv_recv(ep_out
, receive_buffer
, sizeof receive_buffer
);
227 mutex_lock(&sendlock
);
228 /* Data sent out. Update circular buffer */
231 buffer_start
= (buffer_start
+ length
)%BUFFER_SIZE
;
232 buffer_length
-= length
;
234 busy_sending
= false;
240 mutex_unlock(&sendlock
);
245 /* called by usb_core_control_request() */
246 bool usb_serial_control_request(struct usb_ctrlrequest
* req
)
248 bool handled
= false;
249 switch (req
->bRequest
) {
251 logf("serial: unhandeld req %d", req
->bRequest
);
256 #endif /*USB_SERIAL*/