Paparazzi UAS  v6.2.0_stable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
usb_ser_hw.c
Go to the documentation of this file.
1 /*
2  ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
3  2011,2012 Giovanni Di Sirio.
4 
5  This file is part of ChibiOS/RT.
6 
7  ChibiOS/RT is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11 
12  ChibiOS/RT is distributed in the hope that it will be ueful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 
22 
23 #include <stdio.h>
24 #include <string.h>
25 #include "ch.h"
26 #include "hal.h"
27 #include "hal_serial_usb.h"
28 #include "mcu_periph/usb_serial.h"
29 
30 #if HAL_USE_SERIAL_USB
31 
32 #ifndef SERIAL_USB
33 #define SERIAL_USB USBD1
34 #endif
35 
36 #ifndef USBD1_DATA_REQUEST_EP
37 #define USBD1_DATA_REQUEST_EP 1
38 #endif
39 #ifndef USBD1_DATA_AVAILABLE_EP
40 #define USBD1_DATA_AVAILABLE_EP 1
41 #endif
42 #ifndef USBD1_INTERRUPT_REQUEST_EP
43 #define USBD1_INTERRUPT_REQUEST_EP 2
44 #endif
45 
46 #if (CH_KERNEL_MAJOR == 2)
47  static EventListener inputAvailEL = {NULL, NULL, 0, 0};
48 #else
49  static event_listener_t inputAvailEL = {NULL, NULL, 0, 0, 0};
50 #endif
51 /*===========================================================================*/
52 /* USB related stuff. */
53 /*===========================================================================*/
54 
55 
56 
57 /*
58  * USB Device Descriptor.
59  */
60 static const uint8_t vcom_device_descriptor_data[18] = {
61  USB_DESC_DEVICE (0x0110, /* bcdUSB (1.1). */
62  0x02, /* bDeviceClass (CDC). */
63  0x00, /* bDeviceSubClass. */
64  0x00, /* bDeviceProtocol. */
65  0x40, /* bMaxPacketSize. */
66  0x0483, /* idVendor (ST). */
67  0x5740, /* idProduct. */
68  0x0200, /* bcdDevice. */
69  1, /* iManufacturer. */
70  2, /* iProduct. */
71  3, /* iSerialNumber. */
72  1) /* bNumConfigurations. */
73 };
74 
75 /*
76  * Device Descriptor wrapper.
77  */
78 static const USBDescriptor vcom_device_descriptor = {
79  sizeof vcom_device_descriptor_data,
80  vcom_device_descriptor_data
81 };
82 
83 /* Configuration Descriptor tree for a CDC.*/
84 static const uint8_t vcom_configuration_descriptor_data[67] = {
85  /* Configuration Descriptor.*/
86  USB_DESC_CONFIGURATION(67, /* wTotalLength. */
87  0x02, /* bNumInterfaces. */
88  0x01, /* bConfigurationValue. */
89  0, /* iConfiguration. */
90  0xC0, /* bmAttributes (self powered). */
91  50), /* bMaxPower (100mA). */
92  /* Interface Descriptor.*/
93  USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */
94  0x00, /* bAlternateSetting. */
95  0x01, /* bNumEndpoints. */
96  0x02, /* bInterfaceClass (Communications
97  Interface Class, CDC section
98  4.2). */
99  0x02, /* bInterfaceSubClass (Abstract
100  Control Model, CDC section 4.3). */
101  0x01, /* bInterfaceProtocol (AT commands,
102  CDC section 4.4). */
103  0), /* iInterface. */
104  /* Header Functional Descriptor (CDC section 5.2.3).*/
105  USB_DESC_BYTE (5), /* bLength. */
106  USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
107  USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header
108  Functional Descriptor. */
109  USB_DESC_BCD (0x0110), /* bcdCDC. */
110  /* Call Management Functional Descriptor. */
111  USB_DESC_BYTE (5), /* bFunctionLength. */
112  USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
113  USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management
114  Functional Descriptor). */
115  USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */
116  USB_DESC_BYTE (0x01), /* bDataInterface. */
117  /* ACM Functional Descriptor.*/
118  USB_DESC_BYTE (4), /* bFunctionLength. */
119  USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
120  USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract
121  Control Management Descriptor). */
122  USB_DESC_BYTE (0x02), /* bmCapabilities. */
123  /* Union Functional Descriptor.*/
124  USB_DESC_BYTE (5), /* bFunctionLength. */
125  USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
126  USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union
127  Functional Descriptor). */
128  USB_DESC_BYTE (0x00), /* bMasterInterface (Communication
129  Class Interface). */
130  USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class
131  Interface). */
132  /* Endpoint 2 Descriptor.*/
133  USB_DESC_ENDPOINT (USBD1_INTERRUPT_REQUEST_EP|0x80,
134  0x03, /* bmAttributes (Interrupt). */
135  0x0008, /* wMaxPacketSize. */
136  0xFF), /* bInterval. */
137  /* Interface Descriptor.*/
138  USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */
139  0x00, /* bAlternateSetting. */
140  0x02, /* bNumEndpoints. */
141  0x0A, /* bInterfaceClass (Data Class
142  Interface, CDC section 4.5). */
143  0x00, /* bInterfaceSubClass (CDC section
144  4.6). */
145  0x00, /* bInterfaceProtocol (CDC section
146  4.7). */
147  0x00), /* iInterface. */
148  /* Endpoint 3 Descriptor.*/
149  USB_DESC_ENDPOINT (USBD1_DATA_AVAILABLE_EP, /* bEndpointAddress.*/
150  0x02, /* bmAttributes (Bulk). */
151  0x0040, /* wMaxPacketSize. */
152  0x00), /* bInterval. */
153  /* Endpoint 1 Descriptor.*/
154  USB_DESC_ENDPOINT (USBD1_DATA_REQUEST_EP|0x80, /* bEndpointAddress.*/
155  0x02, /* bmAttributes (Bulk). */
156  0x0040, /* wMaxPacketSize. */
157  0x00) /* bInterval. */
158 };
159 
160 /*
161  * Configuration Descriptor wrapper.
162  */
163 static const USBDescriptor vcom_configuration_descriptor = {
164  sizeof vcom_configuration_descriptor_data,
165  vcom_configuration_descriptor_data
166 };
167 
168 /*
169  * U.S. English language identifier.
170  */
171 static const uint8_t vcom_string0[] = {
172  USB_DESC_BYTE(4), /* bLength. */
173  USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
174  USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */
175 };
176 
177 /*
178  * Vendor string.
179  */
180 static const uint8_t vcom_string1[] = {
181  USB_DESC_BYTE(28), /* bLength. */
182  USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
183  'P', 0, 'a', 0, 'p', 0, 'a', 0, 'r', 0, 'a', 0, 'z', 0, 'z', 0,
184  'i', 0, ' ', 0, 'U', 0, 'A', 0, 'V', 0
185 };
186 
187 /*
188  * Device Description string.
189  */
190 static const uint8_t vcom_string2[] = {
191  USB_DESC_BYTE(34), /* bLength. */
192  USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
193  'C', 0, 'D', 0, 'C', 0, ' ', 0, 'S', 0, 'e', 0, 'r', 0, 'i', 0,
194  'a', 0, 'l', 0, ' ', 0, 'S', 0, 'T', 0, 'M', 0, '3', 0, '2', 0
195 };
196 
197 /*
198  * Serial Number string.
199  */
200 static const uint8_t vcom_string3[] = {
201  USB_DESC_BYTE(8), /* bLength. */
202  USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
203  '0' + CH_KERNEL_MAJOR, 0,
204  '0' + CH_KERNEL_MINOR, 0,
205  '0' + CH_KERNEL_PATCH, 0
206 };
207 
208 /*
209  * Strings wrappers array.
210  */
211 static const USBDescriptor vcom_strings[] = {
212  {sizeof vcom_string0, vcom_string0},
213  {sizeof vcom_string1, vcom_string1},
214  {sizeof vcom_string2, vcom_string2},
215  {sizeof vcom_string3, vcom_string3}
216 };
217 
218 
219 static SerialUSBDriver SDU;
220 
221 /*
222  * Handles the GET_DESCRIPTOR callback. All required descriptors must be
223  * handled here.
224  */
225 static const USBDescriptor *get_descriptor(USBDriver *usbp,
226  uint8_t dtype,
227  uint8_t dindex,
228  uint16_t lang) {
229 
230  (void)usbp;
231  (void)lang;
232  switch (dtype) {
233  case USB_DESCRIPTOR_DEVICE:
234  return &vcom_device_descriptor;
235  case USB_DESCRIPTOR_CONFIGURATION:
236  return &vcom_configuration_descriptor;
237  case USB_DESCRIPTOR_STRING:
238  if (dindex < 4)
239  return &vcom_strings[dindex];
240  }
241  return NULL;
242 }
243 
244 
248 static USBInEndpointState ep1instate;
249 
253 static USBOutEndpointState ep1outstate;
254 
258 static const USBEndpointConfig ep1config = {
259  USB_EP_MODE_TYPE_BULK,
260  NULL,
261  sduDataTransmitted,
262  sduDataReceived,
263  0x0040,
264  0x0040,
265  &ep1instate,
266  &ep1outstate,
267  2,
268  NULL
269 };
270 
274 static USBInEndpointState ep2instate;
275 
279 static const USBEndpointConfig ep2config = {
280  USB_EP_MODE_TYPE_INTR,
281  NULL,
282  sduInterruptTransmitted,
283  NULL,
284  0x0010,
285  0x0000,
286  &ep2instate,
287  NULL,
288  1,
289  NULL
290 };
291 
292 
293 
294 /*
295  * Handles the USB driver global events.
296  */
297 static void usb_event(USBDriver *usbp, usbevent_t event) {
298 
299  switch (event) {
300  case USB_EVENT_RESET:
301  return;
302  case USB_EVENT_ADDRESS:
303  return;
304  case USB_EVENT_CONFIGURED:
305  chSysLockFromISR();
306 
307  /* Enables the endpoints specified into the configuration.
308  Note, this callback is invoked from an ISR so I-Class functions
309  must be used.*/
310  usbInitEndpointI(usbp, USBD1_DATA_REQUEST_EP, &ep1config);
311  usbInitEndpointI(usbp, USBD1_INTERRUPT_REQUEST_EP, &ep2config);
312 
313  /* Resetting the state of the CDC subsystem.*/
314  sduConfigureHookI(&SDU);
315 
316  chSysUnlockFromISR();
317  return;
318  case USB_EVENT_UNCONFIGURED:
319  return;
320  case USB_EVENT_SUSPEND:
321  chSysLockFromISR();
322 
323  /* Disconnection event on suspend.*/
324  sduSuspendHookI(&SDU);
325 
326  chSysUnlockFromISR();
327  return;
328  case USB_EVENT_WAKEUP:
329  return;
330  case USB_EVENT_STALLED:
331  return;
332  }
333  return;
334 }
335 
336 /*
337  * Handles the USB driver global events.
338  */
339 static void sof_handler(USBDriver *usbp)
340 {
341  (void)usbp;
342 
343  chSysLockFromISR();
344  sduSOFHookI(&SDU);
345  chSysUnlockFromISR();
346 }
347 
348 /*
349  * Serial over USB driver configuration.
350  */
351 static const USBConfig usbcfg = {
352  usb_event,
353  get_descriptor,
354  sduRequestsHook,
355  sof_handler
356 };
357 
358 static SerialUSBConfig serusbcfg ;
359 
360 USBDriver *usbGetDriver (void)
361 {
362  return serusbcfg.usbp;
363 }
364 
365 
366 
367 bool isUsbConnected(void)
368 {
369  static bool hasEverReceive = FALSE;
370 
371 #if (CH_KERNEL_MAJOR <= 3)
372  if (inputAvailEL.el_listener == NULL)
373 #else
374  if (inputAvailEL.listener == NULL)
375 #endif
376  return FALSE;
377 
378  if (hasEverReceive)
379  return TRUE;
380  else
381  return ((hasEverReceive = chEvtGetAndClearFlags(&inputAvailEL)) != 0);
382 }
383 
384 
385 
386 
387 void usbSerialReset(SerialUSBDriver *sdu)
388 {
389  usbStop(serusbcfg.usbp);
390  usbDisconnectBus(serusbcfg.usbp);
391  sduStop (sdu);
392 
393  chThdSleepMilliseconds(10);
394  sduStart(sdu, &serusbcfg);
395  usbDisconnectBus(serusbcfg.usbp);
396  chThdSleepMilliseconds(900);
397  usbStart(serusbcfg.usbp, &usbcfg);
398  usbConnectBus(serusbcfg.usbp);
399 }
400 
401 
402 /*
403  * For USB telemetry & generic device API
404  */
405 // Periph with generic device API
407 
408 // Functions for the generic device API
409 static int usb_serial_check_free_space(struct usb_serial_periph *p __attribute__((unused)),
410  long *fd __attribute__((unused)),
411  uint16_t len)
412 {
413  return len;
414 }
415 
416 static void usb_serial_transmit(struct usb_serial_periph *p __attribute__((unused)),
417  long fd __attribute__((unused)),
418  uint8_t byte)
419 {
420  streamPut(&SDU, byte);
421 }
422 
423 static void usb_serial_transmit_buffer(struct usb_serial_periph *p __attribute__((unused)),
424  long fd __attribute__((unused)),
425  uint8_t *data, uint16_t len)
426 {
427  streamWrite(&SDU, data, len);
428 }
429 
430 static void usb_serial_send(struct usb_serial_periph *p __attribute__((unused)), long fd __attribute__((unused)))
431 {
432  // TODO
433 }
434 
435 static int usb_serial_char_available(struct usb_serial_periph *p __attribute__((unused)))
436 {
437  // some bytes in the buffer
438  if(p->nb_bytes > 0) {
439  return p->nb_bytes;
440  }
441 
442  uint16_t write_idx = (p->rx_read_idx + p->nb_bytes) % USB_RX_BUFFER_SIZE;
443 
444  // no bytes in the buffer, try to get one
445  msg_t res = ibqGetTimeout(&SDU.ibqueue, TIME_IMMEDIATE);
446  if(res >= 0) {
447  // got a byte. put it in the buffer.
448  p->rx_buf[write_idx] = (uint8_t) res;
449  p->nb_bytes++;
450  return p->nb_bytes;
451  } else {
452  // timeout or queue suspended. No data available.
453  return 0;
454  }
455 }
456 
457 static uint8_t usb_serial_getch(struct usb_serial_periph *p __attribute__((unused)))
458 {
459  if(p->nb_bytes > 0) {
460  uint8_t ret = p->rx_buf[p->rx_read_idx];
461  p->rx_read_idx = (p->rx_read_idx + 1) % USB_RX_BUFFER_SIZE;
462  p->nb_bytes--;
463  return ret;
464  } else {
465  // blocking get
466  return streamGet(&SDU);
467  }
468 }
469 
470 
471 
472 
473 /*
474  * usb init
475  */
476 void VCOM_init()
477 {
478  serusbcfg.usbp = &SERIAL_USB;
479  serusbcfg.bulk_in = USBD1_DATA_REQUEST_EP;
480  serusbcfg.bulk_out = USBD1_DATA_AVAILABLE_EP;
481  serusbcfg.int_in = USBD1_INTERRUPT_REQUEST_EP;
482 
483  sduObjectInit(&SDU);
484  sduStart(&SDU, &serusbcfg);
485 
486  usbDisconnectBus(serusbcfg.usbp);
487  chThdSleepMilliseconds(1000);
488  usbStart(serusbcfg.usbp, &usbcfg);
489  usbConnectBus(serusbcfg.usbp);
490 
491  chEvtRegisterMask(chnGetEventSource(&SDU), &inputAvailEL, CHN_INPUT_AVAILABLE);
492 
493 
494 
495  usb_serial.nb_bytes = 0;
497  usb_serial.reg_addr = &SDU;
498  // Configure generic device
499  usb_serial.device.periph = (void *)(&usb_serial);
500  usb_serial.device.check_free_space = (check_free_space_t) usb_serial_check_free_space;
501  usb_serial.device.put_byte = (put_byte_t) usb_serial_transmit;
502  usb_serial.device.put_buffer = (put_buffer_t) usb_serial_transmit_buffer;
503  usb_serial.device.send_message = (send_message_t) usb_serial_send;
504  usb_serial.device.char_available = (char_available_t) usb_serial_char_available;
505  usb_serial.device.get_byte = (get_byte_t) usb_serial_getch;
506 
507 }
508 
509 
510 int VCOM_putchar(int c) {
511  if(!isUsbConnected()) {
512  return -1;
513  }
514  streamPut(&SDU, c);
515  return c;
516 
517 }
518 
519 int VCOM_getchar(void) {
520  return usb_serial_getch(&usb_serial);
521 }
522 
523 int VCOM_peekchar(int ofs __attribute__((unused))) {
524  // Dummy implementation
525  return 0;
526 }
527 
528 bool VCOM_check_free_space(uint16_t len __attribute__((unused))) {
529  return true;
530 }
531 
532 int VCOM_check_available(void) {
534 }
535 
536 void VCOM_set_linecoding(uint8_t mode __attribute__((unused))) {}
537 
538 void VCOM_allow_linecoding(uint8_t mode __attribute__((unused))) {}
539 
540 void VCOM_send_message(void) {}
541 
542 void VCOM_event(void) {}
543 
544 
545 #endif // HAL_USE_SERIAL_USB
static float p[2][2]
int fd
Definition: serial.c:26
static uint8_t mode
mode holds the current sonar mode mode = 0 used at high altitude, uses 16 wave patterns mode = 1 used...
Definition: sonar_bebop.c:69
#define TRUE
Definition: std.h:4
#define FALSE
Definition: std.h:5
void VCOM_event(void)
Poll usb (required by libopencm3).
Definition: usb_ser_hw.c:468
int VCOM_getchar(void)
Reads one character from VCOM port.
Definition: usb_ser_hw.c:425
int VCOM_putchar(int c)
Writes one character to VCOM port fifo.
Definition: usb_ser_hw.c:397
static int usb_serial_check_free_space(struct usb_serial_periph *p, long *fd, uint16_t len)
Definition: usb_ser_hw.c:526
static void usb_serial_transmit_buffer(struct usb_serial_periph *p, long fd, uint8_t *data, uint16_t len)
Definition: usb_ser_hw.c:540
static void usb_serial_transmit(struct usb_serial_periph *p, long fd, uint8_t byte)
Definition: usb_ser_hw.c:533
int VCOM_check_available(void)
Checks if data available in VCOM buffer.
Definition: usb_ser_hw.c:459
int VCOM_peekchar(int ofs)
Reads one character from VCOM port without removing it from the queue.
Definition: usb_ser_hw.c:438
void VCOM_init(void)
Definition: usb_ser_hw.c:565
void VCOM_send_message(void)
Send data from fifo right now.
Definition: usb_ser_hw.c:487
struct usb_serial_periph usb_serial
Definition: usb_ser_hw.c:523
static uint8_t usb_serial_getch(struct usb_serial_periph *p)
Definition: usb_ser_hw.c:560
static void usb_serial_send(struct usb_serial_periph *p, long fd)
Definition: usb_ser_hw.c:550
static int usb_serial_char_available(struct usb_serial_periph *p)
Definition: usb_ser_hw.c:555
bool VCOM_check_free_space(uint16_t len)
Checks if buffer free in VCOM buffer.
Definition: usb_ser_hw.c:450
arch independent USB API
uint16_t rx_read_idx
Definition: usb_serial.h:43
void VCOM_set_linecoding(uint8_t mode)
struct link_device device
Generic device interface.
Definition: usb_serial.h:48
void VCOM_allow_linecoding(uint8_t mode)
#define USB_RX_BUFFER_SIZE
Definition: usb_serial.h:37
uint16_t nb_bytes
Definition: usb_serial.h:44
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
Definition: vl53l1_types.h:88
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
Definition: vl53l1_types.h:98