Contiki 2.5
uart_usb_lib.c
Go to the documentation of this file.
1 /* This file has been prepared for Doxygen automatic documentation generation.*/
2 /*! \file uart_usb_lib.c *********************************************************************
3  *
4  * \brief
5  * This file controls the UART USB functions.
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 /*_____ I N C L U D E S ____________________________________________________*/
44 
45 #include "config.h"
46 #include "usb_drv.h"
47 #include "usb_descriptors.h"
48 #include "serial/uart_usb_lib.h"
49 #include "cdc_task.h"
50 #include <stdio.h>
51 
52 /**
53  \addtogroup cdctask
54  @{
55  */
56 
57 /*_____ M A C R O S ________________________________________________________*/
58 
59 #ifndef USB_CDC_ACM_HOOK_TX_START
60 #define USB_CDC_ACM_HOOK_TX_START(char)
61 #endif
62 
63 #ifndef USB_CDC_ACM_HOOK_TX_END
64 #define USB_CDC_ACM_HOOK_TX_END(char)
65 #endif
66 
67 #ifndef USB_CDC_ACM_HOOK_CLS_CHANGED
68 #define USB_CDC_ACM_HOOK_CLS_CHANGED(state)
69 #endif
70 
71 #ifndef USB_CDC_ACM_HOOK_CONFIGURED
72 #define USB_CDC_ACM_HOOK_CONFIGURED()
73 #endif
74 
75 #ifndef USB_CDC_ACM_CONF_LOCAL_ECHO
76 #define USB_CDC_ACM_CONF_LOCAL_ECHO 0
77 #endif
78 
79 /*_____ D E F I N I T I O N ________________________________________________*/
80 
81 Uchar tx_counter;
82 Uchar rx_counter;
83 S_line_coding line_coding;
84 
85 /*_____ D E C L A R A T I O N ______________________________________________*/
86 
87 void uart_usb_configure_endpoints() {
88  usb_configure_endpoint(
89  VCP_INT_EP,
90  TYPE_INTERRUPT,
91  DIRECTION_IN,
92  SIZE_32,
93  ONE_BANK,
94  NYET_ENABLED
95  );
96 
97  usb_configure_endpoint(
98  VCP_TX_EP,
99  TYPE_BULK,
100  DIRECTION_IN,
101  SIZE_32,
102  TWO_BANKS,
103  NYET_ENABLED
104  );
105 
106  usb_configure_endpoint(
107  VCP_RX_EP,
108  TYPE_BULK,
109  DIRECTION_OUT,
110  SIZE_32,
111  TWO_BANKS,
112  NYET_ENABLED
113  );
114 
115  Usb_reset_endpoint(VCP_INT_EP);
116  Usb_reset_endpoint(VCP_TX_EP);
117  Usb_reset_endpoint(VCP_RX_EP);
118 
119  USB_CDC_ACM_HOOK_CONFIGURED();
120 }
121 
122 
123 int usb_stdout_putchar(char c, FILE *stream)
124 {
125  // Preserve the currently selected endpoint
126  uint8_t uenum = UENUM;
127 
128  // send to USB port
129  // don't send anything if USB can't accept chars
130  Usb_select_endpoint(VCP_TX_EP);
131 
132  if(usb_endpoint_wait_for_write_enabled()!=0)
133  return 0;
134 
135  if(c=='\n')
136  uart_usb_putchar('\r');
137 
138  if(c!='\r')
139  uart_usb_putchar(c);
140 
141  // Restore previously selected endpoint
142  UENUM = uenum;
143 
144  return 0;
145 }
146 
147 static FILE usb_stdout = FDEV_SETUP_STREAM(usb_stdout_putchar,
148  NULL,
149  _FDEV_SETUP_WRITE);
150 
151 /**
152  * @brief Initializes the uart_usb library
153  */
154 void uart_usb_init(void)
155 {
156  tx_counter = 0;
157  rx_counter = 0;
158 }
159 
160 void uart_usb_set_stdout(void)
161 {
162  stdout = &usb_stdout;
163 }
164 
165 
166 static uint8_t uart_usb_control_line_state = 0;
167 
168 uint8_t uart_usb_get_control_line_state(void) {
169  return uart_usb_control_line_state;
170 }
171 
172 
173 void uart_usb_set_control_line_state(uint8_t control_line_state)
174 {
175  uart_usb_control_line_state = control_line_state;
176  USB_CDC_ACM_HOOK_CLS_CHANGED(control_line_state);
177 }
178 
179 
180 /**
181  * @brief This function checks if the USB emission buffer is ready to accept at
182  * at least 1 byte
183  *
184  * @retval TRUE if the firmware can write a new byte to transmit.
185  * @retval FALSE otherwise
186  */
188 {
189  Usb_select_endpoint(VCP_TX_EP);
190  if (!Is_usb_write_enabled())
191  {
192  return FALSE;
193  }
194  return TRUE;
195 }
196 
197 /**
198  * @brief This function fills the USB transmit buffer with the new data. This buffer
199  * is sent if complete. To flush this buffer before waiting full, launch
200  * the uart_usb_flush() function.
201  *
202  * @param data_to_send Data to send
203  *
204  * @return data_to_send Data that was sent
205  */
206 int uart_usb_putchar(int data_to_send)
207 {
208  // Preserve the currently selected endpoint
209  uint8_t uenum = UENUM;
210 
211  USB_CDC_ACM_HOOK_TX_START(data_to_send);
212 
213  Usb_select_endpoint(VCP_TX_EP);
214 
215  if(!uart_usb_tx_ready()) {
216  data_to_send=-1;
217  goto bail;
218  }
219 
220  Usb_write_byte(data_to_send);
221  tx_counter++;
222 
223  //If Endpoint full -> flush
224  if(!Is_usb_write_enabled())
225  uart_usb_flush();
226 
227  USB_CDC_ACM_HOOK_TX_END(data_to_send);
228 
229 bail:
230  // Restore previously selected endpoint
231  UENUM = uenum;
232 
233  return data_to_send;
234 }
235 
236 /**
237  * @brief This function checks if a character has been received on the USB bus.
238  *
239  * @return bit (true if a byte is ready to be read)
240  */
242 {
243  if (!rx_counter)
244  {
245  // Preserve the currently selected endpoint
246  uint8_t uenum = UENUM;
247  Usb_select_endpoint(VCP_RX_EP);
248  if (Is_usb_receive_out())
249  {
250  rx_counter = Usb_byte_counter();
251  if (!rx_counter)
252  {
254  }
255  }
256  // Restore previously selected endpoint
257  UENUM = uenum;
258  }
259  return (rx_counter!=0);
260 }
261 
262 /**
263  * @brief This function reads one byte from the USB bus
264  *
265  * If one byte is present in the USB fifo, this byte is returned. If no data
266  * is present in the USB fifo, this function waits for USB data.
267  *
268  * @return U8 byte received
269  */
271 {
272  register Uchar data_rx;
273 
274  // Preserve the currently selected endpoint
275  uint8_t uenum = UENUM;
276 
277  Usb_select_endpoint(VCP_RX_EP);
278  if (!rx_counter) while (!uart_usb_test_hit());
279  data_rx=Usb_read_byte();
280  rx_counter--;
281  if (!rx_counter) Usb_ack_receive_out();
282 
283 #if USB_CDC_ACM_CONF_LOCAL_ECHO
284  //Local echo
285  uart_usb_putchar(data_rx);
286 #endif
287 
288  // Restore previously selected endpoint
289  UENUM = uenum;
290 
291  return data_rx;
292 }
293 
294 
295 /**
296  * @brief This function sends the data stored in the USB transmit buffer.
297  * This function does nothing if there is no data in the buffer.
298  */
299 void uart_usb_flush (void)
300 {
301  // Preserve the currently selected endpoint
302  uint8_t uenum = UENUM;
303 
304  Usb_select_endpoint(VCP_TX_EP);
305  Usb_send_in();
306  tx_counter = 0;
307  usb_endpoint_wait_for_write_enabled();
308 
309  // Restore previously selected endpoint
310  UENUM = uenum;
311 }
312 
313 /** @} */