Contiki 2.5
usb_drv.c
Go to the documentation of this file.
1 /* This file has been prepared for Doxygen automatic documentation generation.*/
2 /*! \file usb_drv.c************************************************************
3  *
4  * \brief
5  * This file contains the USB driver routines.
6  *
7  * \addtogroup usbstick
8  *
9  * \author
10  * Atmel Corporation: http://www.atmel.com \n
11  * Support email: avr@atmel.com
12  *
13  ******************************************************************************/
14 /* Copyright (c) 2008 ATMEL Corporation
15  All rights reserved.
16 
17  Redistribution and use in source and binary forms, with or without
18  modification, are permitted provided that the following conditions are met:
19 
20  * Redistributions of source code must retain the above copyright
21  notice, this list of conditions and the following disclaimer.
22  * Redistributions in binary form must reproduce the above copyright
23  notice, this list of conditions and the following disclaimer in
24  the documentation and/or other materials provided with the
25  distribution.
26  * Neither the name of the copyright holders nor the names of
27  contributors may be used to endorse or promote products derived
28  from this software without specific prior written permission.
29 
30  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
34  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40  POSSIBILITY OF SUCH DAMAGE.
41 */
42 
43 /**
44  \addtogroup usbdriver
45  @{
46  */
47 
48 //_____ I N C L U D E S ____________________________________________________
49 
50 #include "config.h"
51 #include "conf_usb.h"
52 #include "usb_drv.h"
53 #include <util/delay.h>
54 
55 //_____ M A C R O S ________________________________________________________
56 
57 //_____ D E C L A R A T I O N ______________________________________________
58 
59 #if (USB_DEVICE_FEATURE==DISABLED && USB_HOST_FEATURE==DISABLED)
60  #error at least one of USB_DEVICE_FEATURE or USB_HOST_FEATURE should be unabled
61 #endif
62 
63 #if (USB_DEVICE_FEATURE == ENABLED)
64 
65 #define USB_ENDPOINT_WAIT_TIMEOUT 250
66 
67 U8 usb_endpoint_wait_for_write_enabled() {
68 #if USB_ENDPOINT_WAIT_TIMEOUT
69  U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT;
70  while(timeout) {
71  if(Is_usb_sof()) {
72  Usb_ack_sof();
73  timeout--;
74  }
75 #else
76  while(1) {
77 #endif
79  return 0;
80  if((!Is_usb_enabled()) || Is_usb_detached())
81  return 1;
83  return 2;
85  return 3;
86  }
87  return 10;
88 }
89 
90 U8 usb_endpoint_wait_for_read_control_enabled() {
91 #if USB_ENDPOINT_WAIT_TIMEOUT
92  U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT;
93  while(timeout) {
94  if(Is_usb_sof()) {
95  Usb_ack_sof();
96  timeout--;
97  }
98 #else
99  while(1) {
100 #endif
102  return 0;
103  if((!Is_usb_enabled()) || Is_usb_detached())
104  return 1;
106  return 2;
108  return 3;
109  }
110  return 10;
111 }
112 
113 
114 U8 usb_endpoint_wait_for_IN_ready() {
115 #if USB_ENDPOINT_WAIT_TIMEOUT
116  U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT;
117  while(timeout) {
118  if(Is_usb_sof()) {
119  Usb_ack_sof();
120  timeout--;
121  }
122 #else
123  while(1) {
124 #endif
125  if(Is_usb_in_ready())
126  return 0;
127  if((!Is_usb_enabled()) || Is_usb_detached())
128  return 1;
130  return 2;
132  return 3;
133  }
134  return 10;
135 }
136 
137 
138 U8 usb_endpoint_wait_for_receive_out() {
139 #if USB_ENDPOINT_WAIT_TIMEOUT
140  U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT;
141  while(timeout) {
142  if(Is_usb_sof()) {
143  Usb_ack_sof();
144  timeout--;
145  }
146 #else
147  while(1) {
148 #endif
149  if(Is_usb_receive_out())
150  return 0;
151  if((!Is_usb_enabled()) || Is_usb_detached())
152  return 1;
154  return 2;
156  return 3;
157  }
158  return 10;
159 }
160 
161 //! usb_configure_endpoint.
162 //!
163 //! This function configures an endpoint with the selected type.
164 //!
165 //! @param config0
166 //! @param config1
167 //!
168 //! @return Is_endpoint_configured().
169 //!
170 U8 usb_config_ep(U8 config0, U8 config1)
171 {
173  UECFG0X = config0;
174  UECFG1X = (UECFG1X & (1<<ALLOC)) | config1;
176  return (Is_endpoint_configured());
177 }
178 
179 //! usb_select_endpoint_interrupt.
180 //!
181 //! This function select the endpoint where an event occurs and returns the
182 //! number of this endpoint. If no event occurs on the endpoints, this
183 //! function returns 0.
184 //!
185 //! @return 0 endpoint number.
186 //!
188 {
189 U8 interrupt_flags;
190 U8 ep_num;
191 
192  ep_num = 0;
193  interrupt_flags = Usb_interrupt_flags();
194 
195  while(ep_num < MAX_EP_NB)
196  {
197  if (interrupt_flags & 1)
198  {
199  return (ep_num);
200  }
201  else
202  {
203  ep_num++;
204  interrupt_flags = interrupt_flags >> 1;
205  }
206  }
207  return 0;
208 }
209 
210 //! usb_send_packet.
211 //!
212 //! This function moves the data pointed by tbuf to the selected endpoint fifo
213 //! and sends it through the USB.
214 //!
215 //!
216 //! @param ep_num number of the addressed endpoint
217 //! @param tbuf address of the first data to send
218 //! @param data_length number of bytes to send
219 //!
220 //! @return remaining_length address of the next U8 to send.
221 //!
222 //! Example:
223 //! usb_send_packet(3,&first_data,0x20); // send packet on the endpoint #3
224 //! while(!(Usb_tx_complete)); // wait packet ACK'ed by the Host
225 //! Usb_clear_tx_complete(); // acknowledge the transmit
226 //!
227 //! Note:
228 //! tbuf is incremented of 'data_length'.
229 //!
230 U8 usb_send_packet(U8 ep_num, U8* tbuf, U8 data_length)
231 {
232 U8 remaining_length;
233 
234  remaining_length = data_length;
235  Usb_select_endpoint(ep_num);
236  while(Is_usb_write_enabled() && (0 != remaining_length))
237  {
238  Usb_write_byte(*tbuf);
239  remaining_length--;
240  tbuf++;
241  }
242  return remaining_length;
243 }
244 
245 //! usb_read_packet.
246 //!
247 //! This function moves the data stored in the selected endpoint fifo to
248 //! the address specified by *rbuf.
249 //!
250 //!
251 //! @param ep_num number of the addressed endpoint
252 //! @param rbuf aaddress of the first data to write with the USB data
253 //! @param data_length number of bytes to read
254 //!
255 //! @return remaining_length address of the next U8 to send.
256 //!
257 //! Example:
258 //! while(!(Usb_rx_complete)); // wait new packet received
259 //! usb_read_packet(4,&first_data,usb_get_nb_byte); // read packet from ep 4
260 //! Usb_clear_rx(); // acknowledge the transmit
261 //!
262 //! Note:
263 //! rbuf is incremented of 'data_length'.
264 //!
265 U8 usb_read_packet(U8 ep_num, U8* rbuf, U8 data_length)
266 {
267 U8 remaining_length;
268 
269  remaining_length = data_length;
270  Usb_select_endpoint(ep_num);
271 
272  while(Is_usb_read_enabled() && (0 != remaining_length))
273  {
274  *rbuf = Usb_read_byte();
275  remaining_length--;
276  rbuf++;
277  }
278  return remaining_length;
279 }
280 
281 //! usb_halt_endpoint.
282 //!
283 //! This function sends a STALL handshake for the next Host request. A STALL
284 //! handshake will be send for each next request untill a SETUP or a Clear Halt
285 //! Feature occurs for this endpoint.
286 //!
287 //! @param ep_num number of the addressed endpoint
288 //!
289 void usb_halt_endpoint (U8 ep_num)
290 {
291  Usb_select_endpoint(ep_num);
293 }
294 
295 //! usb_init_device.
296 //!
297 //! This function initializes the USB device controller and
298 //! configures the Default Control Endpoint.
299 //!
300 //! @retval FALSE if not Is_usb_id_device() returns FALSE
301 //! @return usb_configure_endpoint() status
302 //!
304 {
305  U8 rv = FALSE;
306 
307  Usb_select_device();
308  if(Is_usb_id_device())
309  {
310  Usb_select_endpoint(EP_CONTROL);
312  {
313 #if (USB_LOW_SPEED_DEVICE==DISABLE)
314  rv = usb_configure_endpoint(EP_CONTROL, \
315  TYPE_CONTROL, \
316  DIRECTION_OUT, \
317  SIZE_64, \
318  ONE_BANK, \
319  NYET_DISABLED);
320 #else
321  rv = usb_configure_endpoint(EP_CONTROL, \
322  TYPE_CONTROL, \
323  DIRECTION_OUT, \
324  SIZE_8, \
325  ONE_BANK, \
326  NYET_DISABLED);
327 #endif
328 
329  }
330  }
331  return rv;
332 }
333 
334 #endif
335 
336 //! ---------------------------------------------------------
337 //! ------------------ HOST ---------------------------------
338 //! ---------------------------------------------------------
339 
340 #if (USB_HOST_FEATURE == ENABLED)
341 
342 //! usb_configure_pipe.
343 //!
344 //! This function configures a pipe with the selected type.
345 //!
346 //! @param config0
347 //! @param config1
348 //!
349 //! @return Is_endpoint_configured().
350 U8 host_config_pipe(U8 config0, U8 config1)
351 {
353  UPCFG0X = config0;
354  UPCFG1X = config1;
356  return (Is_pipe_configured());
357 }
358 
359 //! host_determine_pipe_size.
360 //!
361 //! This function returns the size configuration register value according
362 //! to the endpint size detected inthe device enumeration process.
363 //!
364 //! @retval SIZE_8 pipe size register value.
365 //! @retval SIZE_16 pipe size register value.
366 //! @retval SIZE_32 pipe size register value.
367 //! @retval SIZE_64 pipe size register value.
368 //! @retval SIZE_128 pipe size register value.
369 //! @retval SIZE_256 pipe size register value.
370 //! @retval SIZE_512 pipe size register value.
371 //! @retval SIZE_1024 pipe size register value.
372 //!
373 U8 host_determine_pipe_size(U16 size)
374 {
375  if(size <= 8 ) {return (SIZE_8 );}
376  else if(size <= 16 ) {return (SIZE_16 );}
377  else if(size <= 32 ) {return (SIZE_32 );}
378  else if(size <= 64 ) {return (SIZE_64 );}
379  else if(size <= 128) {return (SIZE_128 );}
380  else if(size <= 256) {return (SIZE_256 );}
381  else if(size <= 512) {return (SIZE_512 );}
382  else {return (SIZE_1024);}
383 
384 }
385 
386 //! host_disable_all_pipe.
387 //!
388 //! This function disable all pipes for the host controller
389 //! Usefull to execute upon device disconnection.
390 //!
391 void host_disable_all_pipe(void)
392 {
393 U8 i;
394  for (i=0;i<7;i++)
395  {
396  Host_reset_pipe(i);
397  Host_select_pipe(i);
400  }
401 }
402 
403 //! @brief Returns the pipe number that generates a USB communication interrupt
404 //!
405 //! This function sould be called only when an interrupt has been detected. Otherwize
406 //! the return value is incorect
407 //!
408 //! @retval MAX_EP_NB + 1 - pipe_number
409 //!
410 U8 usb_get_nb_pipe_interrupt(void)
411 {
412 U8 interrupt_flags;
413 U8 i;
414 
415  interrupt_flags = Host_get_pipe_interrupt();
416  for(i=0;i< MAX_EP_NB;i++)
417  {
418  if (interrupt_flags & (1<<i))
419  {
420  return (i);
421  }
422  }
423  // This return should never occurs ....
424  return MAX_EP_NB+1;
425 }
426 
427 
428 #endif // USB_HOST_FEATURE == ENABLED
429 
430 /** @} */