1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2007 by Christian Gmeiner
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
30 #define BUFFER_SIZE 16384 /* No larger, because of controller limitations */
31 static unsigned char _send_buffer
[BUFFER_SIZE
] __attribute__((aligned(32)));
32 static unsigned char* send_buffer
;
34 static unsigned char _receive_buffer
[512] __attribute__((aligned(32)));
35 static unsigned char* receive_buffer
;
36 static bool busy_sending
= false;
37 static int buffer_start
;
38 static int buffer_length
;
39 static bool active
= false;
41 static struct mutex sendlock
;
43 /* called by usb_code_init() */
44 void usb_serial_init(void)
47 send_buffer
= (void*)UNCACHED_ADDR(&_send_buffer
);
48 receive_buffer
= (void*)UNCACHED_ADDR(&_receive_buffer
);
53 mutex_init(&sendlock
);
56 void usb_serial_exit(void)
61 static void sendout(void)
63 if(buffer_start
+buffer_length
> BUFFER_SIZE
)
65 /* Buffer wraps. Only send the first part */
66 usb_drv_send_nonblocking(EP_SERIAL
, &send_buffer
[buffer_start
],(BUFFER_SIZE
- buffer_start
));
71 usb_drv_send_nonblocking(EP_SERIAL
, &send_buffer
[buffer_start
],buffer_length
);
76 void usb_serial_send(unsigned char *data
,int length
)
80 mutex_lock(&sendlock
);
81 if(buffer_start
+buffer_length
> BUFFER_SIZE
)
83 /* current buffer wraps, so new data can't */
84 int available_space
= BUFFER_SIZE
- buffer_length
;
85 length
=MIN(length
,available_space
);
86 memcpy(&send_buffer
[(buffer_start
+buffer_length
)%BUFFER_SIZE
],data
,MIN(length
,available_space
));
87 buffer_length
+=length
;
91 /* current buffer doesn't wrap, so new data might */
92 int available_end_space
= (BUFFER_SIZE
- (buffer_start
+ buffer_length
));
93 int first_chunk
= MIN(length
,available_end_space
);
94 memcpy(&send_buffer
[buffer_start
+ buffer_length
],data
,first_chunk
);
96 buffer_length
+=first_chunk
;
100 memcpy(&send_buffer
[0],&data
[first_chunk
],MIN(length
,buffer_start
));
101 buffer_length
+=MIN(length
,buffer_start
);
106 /* Do nothing. The transfer completion handler will pick it up */
112 mutex_unlock(&sendlock
);
115 /* called by usb_core_transfer_complete() */
116 void usb_serial_transfer_complete(bool in
, int status
, int length
)
120 logf("serial: %s", receive_buffer
);
121 /* Data received. TODO : Do something with it ? */
122 usb_drv_recv(EP_SERIAL
, receive_buffer
, sizeof _receive_buffer
);
126 mutex_lock(&sendlock
);
127 /* Data sent out. Update circular buffer */
130 buffer_start
= (buffer_start
+ length
)%BUFFER_SIZE
;
131 buffer_length
-= length
;
133 busy_sending
= false;
139 mutex_unlock(&sendlock
);
144 /* called by usb_core_control_request() */
145 bool usb_serial_control_request(struct usb_ctrlrequest
* req
)
147 bool handled
= false;
148 switch (req
->bRequest
) {
149 case USB_REQ_SET_CONFIGURATION
:
150 logf("serial: set config");
151 /* prime rx endpoint */
152 usb_drv_recv(EP_SERIAL
, receive_buffer
, sizeof _receive_buffer
);
155 /* we come here too after a bus reset, so reset some data */
156 busy_sending
= false;
161 logf("serial: unhandeld req %d", req
->bRequest
);
167 #endif /*USB_SERIAL*/