#include "usb_usart.h" #include #include "sphere_shell.h" #include #include "powersave.h" SerialUSBDriver SDU1; static const uint8_t vcom_device_descriptor_data[18] = { USB_DESC_DEVICE (0x0110, /* bcdUSB (1.1). */ 0x02, /* bDeviceClass (CDC). */ 0x00, /* bDeviceSubClass. */ 0x00, /* bDeviceProtocol. */ 0x40, /* bMaxPacketSize. */ 0x0483, /* idVendor (ST). */ 0x5740, /* idProduct. */ 0x0200, /* bcdDevice. */ 1, /* iManufacturer. */ 2, /* iProduct. */ 3, /* iSerialNumber. */ 1) /* bNumConfigurations. */ }; static const USBDescriptor vcom_device_descriptor = { sizeof vcom_device_descriptor_data, vcom_device_descriptor_data }; static const uint8_t vcom_configuration_descriptor_data[67] = { /* Configuration Descriptor.*/ USB_DESC_CONFIGURATION(67, /* wTotalLength. */ 0x02, /* bNumInterfaces. */ 0x01, /* bConfigurationValue. */ 0, /* iConfiguration. */ 0xC0, /* bmAttributes (self powered). */ 50), /* bMaxPower (100mA). */ /* Interface Descriptor.*/ USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */ 0x00, /* bAlternateSetting. */ 0x01, /* bNumEndpoints. */ 0x02, /* bInterfaceClass (Communications Interface Class, CDC section 4.2). */ 0x02, /* bInterfaceSubClass (Abstract Control Model, CDC section 4.3). */ 0x01, /* bInterfaceProtocol (AT commands, CDC section 4.4). */ 0), /* iInterface. */ /* Header Functional Descriptor (CDC section 5.2.3).*/ USB_DESC_BYTE (5), /* bLength. */ USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header Functional Descriptor. */ USB_DESC_BCD (0x0110), /* bcdCDC. */ /* Call Management Functional Descriptor. */ USB_DESC_BYTE (5), /* bFunctionLength. */ USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management Functional Descriptor). */ USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */ USB_DESC_BYTE (0x01), /* bDataInterface. */ /* ACM Functional Descriptor.*/ USB_DESC_BYTE (4), /* bFunctionLength. */ USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract Control Management Descriptor). */ USB_DESC_BYTE (0x02), /* bmCapabilities. */ /* Union Functional Descriptor.*/ USB_DESC_BYTE (5), /* bFunctionLength. */ USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union Functional Descriptor). */ USB_DESC_BYTE (0x00), /* bMasterInterface (Communication Class Interface). */ USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class Interface). */ /* Endpoint 2 Descriptor.*/ USB_DESC_ENDPOINT (USB_CDC_INTERRUPT_REQUEST_EP|0x80, 0x03, /* bmAttributes (Interrupt). */ 0x0008, /* wMaxPacketSize. */ 0xFF), /* bInterval. */ /* Interface Descriptor.*/ USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */ 0x00, /* bAlternateSetting. */ 0x02, /* bNumEndpoints. */ 0x0A, /* bInterfaceClass (Data Class Interface, CDC section 4.5). */ 0x00, /* bInterfaceSubClass (CDC section 4.6). */ 0x00, /* bInterfaceProtocol (CDC section 4.7). */ 0x00), /* iInterface. */ /* Endpoint 3 Descriptor.*/ USB_DESC_ENDPOINT (USB_CDC_DATA_AVAILABLE_EP, /* bEndpointAddress.*/ 0x02, /* bmAttributes (Bulk). */ 0x0040, /* wMaxPacketSize. */ 0x00), /* bInterval. */ /* Endpoint 1 Descriptor.*/ USB_DESC_ENDPOINT (USB_CDC_DATA_REQUEST_EP|0x80, /* bEndpointAddress.*/ 0x02, /* bmAttributes (Bulk). */ 0x0040, /* wMaxPacketSize. */ 0x00) /* bInterval. */ }; /* * Configuration Descriptor wrapper. */ static const USBDescriptor vcom_configuration_descriptor = { sizeof vcom_configuration_descriptor_data, vcom_configuration_descriptor_data }; /* * U.S. English language identifier. */ static const uint8_t vcom_string0[] = { USB_DESC_BYTE(4), /* bLength. */ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */ }; /* * Vendor string. */ static const uint8_t vcom_string1[] = { USB_DESC_BYTE(32), /* bLength. */ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ 'P', 0, 'e', 0, 't', 0, 't', 0, 'e', 0, 'r', 0, 'i', 0, ' ', 0, 'A', 0, 'i', 0, 'm', 0, 'o', 0, 'n', 0, 'e', 0, 'n', 0 }; /* * Device Description string. */ static const uint8_t vcom_string2[] = { USB_DESC_BYTE(22), /* bLength. */ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ 'O', 0, 't', 0, 'o', 0, 'n', 0, ' ', 0, 'p', 0, 'a', 0, 'l', 0, 'l', 0, 'o', 0 }; /* * Serial Number string. */ static const uint8_t vcom_string3[] = { USB_DESC_BYTE(8), /* bLength. */ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ '1', 0, '2', 0, '3', 0 }; /* * Strings wrappers array. */ static const USBDescriptor vcom_strings[] = { {sizeof vcom_string0, vcom_string0}, {sizeof vcom_string1, vcom_string1}, {sizeof vcom_string2, vcom_string2}, {sizeof vcom_string3, vcom_string3} }; /* * Handles the GET_DESCRIPTOR callback. All required descriptors must be * handled here. */ static const USBDescriptor *get_descriptor(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t lang) { (void)usbp; (void)lang; switch (dtype) { case USB_DESCRIPTOR_DEVICE: return &vcom_device_descriptor; case USB_DESCRIPTOR_CONFIGURATION: return &vcom_configuration_descriptor; case USB_DESCRIPTOR_STRING: if (dindex < 4) return &vcom_strings[dindex]; } return NULL; } /** * @brief EP1 initialization structure (IN only). */ static const USBEndpointConfig ep1config = { USB_EP_MODE_TYPE_BULK | USB_EP_MODE_PACKET, NULL, sduDataTransmitted, NULL, 0x0040, 0x0000, NULL, NULL }; /** * @brief EP2 initialization structure (IN only). */ static const USBEndpointConfig ep2config = { USB_EP_MODE_TYPE_INTR | USB_EP_MODE_PACKET, NULL, sduInterruptTransmitted, NULL, 0x0010, 0x0000, NULL, NULL }; /** * @brief EP3 initialization structure (OUT only). */ static const USBEndpointConfig ep3config = { USB_EP_MODE_TYPE_BULK | USB_EP_MODE_PACKET, NULL, NULL, sduDataReceived, 0x0000, 0x0040, NULL, NULL }; /* * Handles the USB driver global events. */ static void usb_event(USBDriver *usbp, usbevent_t event) { switch (event) { case USB_EVENT_ADDRESS: return; case USB_EVENT_CONFIGURED: /* Enables the endpoints specified into the configuration. Note, this callback is invoked from an ISR so I-Class functions must be used.*/ chSysLockFromIsr(); usbInitEndpointI(usbp, USB_CDC_DATA_REQUEST_EP, &ep1config); usbInitEndpointI(usbp, USB_CDC_INTERRUPT_REQUEST_EP, &ep2config); usbInitEndpointI(usbp, USB_CDC_DATA_AVAILABLE_EP, &ep3config); chSysUnlockFromIsr(); return; case USB_EVENT_SUSPEND: return; case USB_EVENT_WAKEUP: return; case USB_EVENT_RESET: return; case USB_EVENT_STALLED: return; } return; } /* * Serial over USB driver configuration. */ static const SerialUSBConfig serusbcfg = { &USBD1, { usb_event, get_descriptor, sduRequestsHook, NULL } }; PowersaveStream PSDU1; static const ShellConfig usb_shellconfig = { (BaseSequentialStream*)&PSDU1, shell_commands }; static WORKING_AREA(usb_shellstack, 512); Thread *usb_shell = NULL; void start_usb_usart() { if (SYSCFG->PMC != 0) { // Signal to host that we are reconnecting SYSCFG->PMC = 0; chThdSleepMilliseconds(500); } sduObjectInit(&SDU1); sduStart(&SDU1, &serusbcfg); PowersaveStreamInit(&PSDU1, (BaseChannel*)&SDU1); SYSCFG->PMC = 1; } void stop_usb_usart() { sduStop(&SDU1); SYSCFG->PMC = 0; } void check_usb_usart() { if (USBD1.state == USB_ACTIVE && (usb_shell == NULL || chThdTerminated(usb_shell))) { usb_shell = shellCreateStatic(&usb_shellconfig, usb_shellstack, sizeof(usb_shellstack), NORMALPRIO); } }