Fork of https://developer.mbed.org/users/bscott/code/STM32_USBDevice/
Fork of STM32_USBDevice by
USBSerial/USBWebUSBSerial.cpp@79:d28244984385, 2018-07-25 (annotated)
- Committer:
- Troels Nilsson
- Date:
- Wed Jul 25 14:04:48 2018 +0200
- Revision:
- 79:d28244984385
- Parent:
- 78:ba3f68a86e6d
Merge feature_WebUSB into default
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Troels Nilsson |
76:eef92651f52f | 1 | #include "USBWebUSBSerial.h" |
Troels Nilsson |
77:a98f786d05d4 | 2 | #include "CriticalSectionLock.h" |
Troels Nilsson |
76:eef92651f52f | 3 | |
Troels Nilsson |
76:eef92651f52f | 4 | static uint8_t cdc_line_coding[7]= {0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08}; |
Troels Nilsson |
76:eef92651f52f | 5 | |
Troels Nilsson |
76:eef92651f52f | 6 | #define DEFAULT_CONFIGURATION (1) |
Troels Nilsson |
76:eef92651f52f | 7 | |
Troels Nilsson |
76:eef92651f52f | 8 | #define CDC_SET_LINE_CODING 0x20 |
Troels Nilsson |
76:eef92651f52f | 9 | #define CDC_GET_LINE_CODING 0x21 |
Troels Nilsson |
76:eef92651f52f | 10 | #define CDC_SET_CONTROL_LINE_STATE 0x22 |
Troels Nilsson |
76:eef92651f52f | 11 | |
Troels Nilsson |
76:eef92651f52f | 12 | // USB standard values |
Troels Nilsson |
76:eef92651f52f | 13 | #define USB_CS_INTERFACE 0x24 |
Troels Nilsson |
76:eef92651f52f | 14 | #define USB_HEADER_FUNCTION_DESCRIPTOR_TYPE 0x00 |
Troels Nilsson |
76:eef92651f52f | 15 | #define USB_CALL_MANAGEMENT_FUNCTION_DESCRIPTOR_TYPE 0x01 |
Troels Nilsson |
76:eef92651f52f | 16 | #define USB_ABSTRACT_CONTROL_MANAGEMENT_FUNCTION_DESCRIPTOR_TYPE 0x02 |
Troels Nilsson |
76:eef92651f52f | 17 | #define USB_UNION_INTERFACE_FUNCTION_DESCRIPTOR_TYPE 0x06 |
Troels Nilsson |
76:eef92651f52f | 18 | #define PLATFORM_DEVICE_CAPABILITY_TYPE 0x05 |
Troels Nilsson |
76:eef92651f52f | 19 | |
Troels Nilsson |
76:eef92651f52f | 20 | #define USB_CDC_CLASS 0x02 |
Troels Nilsson |
76:eef92651f52f | 21 | #define USB_ACM_SUBCLASS 0x02 |
Troels Nilsson |
76:eef92651f52f | 22 | #define USB_CDC_DATA_CLASS 0x0A |
Troels Nilsson |
76:eef92651f52f | 23 | #define USB_CUSTOM_CLASS 0xFF |
Troels Nilsson |
76:eef92651f52f | 24 | |
Troels Nilsson |
76:eef92651f52f | 25 | // MS OS 2.0 descriptor types |
Troels Nilsson |
76:eef92651f52f | 26 | #define MS_OS_20_SET_HEADER_DESCRIPTOR 0x00 |
Troels Nilsson |
76:eef92651f52f | 27 | #define MS_OS_20_SUBSET_HEADER_CONFIGURATION 0x01 |
Troels Nilsson |
76:eef92651f52f | 28 | #define MS_OS_20_SUBSET_HEADER_FUNCTION 0x02 |
Troels Nilsson |
76:eef92651f52f | 29 | #define MS_OS_20_FEATURE_COMPATIBLE_ID 0x03 |
Troels Nilsson |
76:eef92651f52f | 30 | #define MS_OS_20_FEATURE_REG_PROPERTY 0x04 |
Troels Nilsson |
76:eef92651f52f | 31 | #define MS_OS_20_FEATURE_MIN_RESUME_TIME 0x05 |
Troels Nilsson |
76:eef92651f52f | 32 | #define MS_OS_20_FEATURE_MODEL_ID 0x06 |
Troels Nilsson |
76:eef92651f52f | 33 | #define MS_OS_20_FEATURE_CCGP_DEVICE 0x07 |
Troels Nilsson |
76:eef92651f52f | 34 | |
Troels Nilsson |
76:eef92651f52f | 35 | #define MS_OS_20_DESCRIPTOR_INDEX 0x07 |
Troels Nilsson |
76:eef92651f52f | 36 | #define MS_OS_20_DESCRIPTOR_LENGTH 178 |
Troels Nilsson |
76:eef92651f52f | 37 | |
Troels Nilsson |
76:eef92651f52f | 38 | // Vendor commands |
Troels Nilsson |
76:eef92651f52f | 39 | #define WINUSB_VENDOR_CODE 0x01 |
Troels Nilsson |
76:eef92651f52f | 40 | #define SET_WEBUSB_ACTIVE_VENDOR_CODE 0xAA |
Troels Nilsson |
76:eef92651f52f | 41 | |
Troels Nilsson |
76:eef92651f52f | 42 | // Control Line State bits |
Troels Nilsson |
76:eef92651f52f | 43 | #define CLS_DTR (1 << 0) |
Troels Nilsson |
76:eef92651f52f | 44 | #define CLS_RTS (1 << 1) |
Troels Nilsson |
76:eef92651f52f | 45 | |
Troels Nilsson |
76:eef92651f52f | 46 | #ifdef USB_DEVICE_WRITE_BLOCKING_TIMEOUT_MS |
Troels Nilsson |
76:eef92651f52f | 47 | #define WEBUSB_WRITE_TIMEOUT (USB_DEVICE_WRITE_BLOCKING_TIMEOUT_MS) |
Troels Nilsson |
76:eef92651f52f | 48 | #else |
Troels Nilsson |
76:eef92651f52f | 49 | #define WEBUSB_WRITE_TIMEOUT 1000 |
Troels Nilsson |
76:eef92651f52f | 50 | #endif |
Troels Nilsson |
76:eef92651f52f | 51 | |
Troels Nilsson |
76:eef92651f52f | 52 | |
Troels Nilsson |
76:eef92651f52f | 53 | uint8_t USBWebUSBSerial::s_MSOS2Descriptor[] = |
Troels Nilsson |
76:eef92651f52f | 54 | { |
Troels Nilsson |
76:eef92651f52f | 55 | // Microsoft OS 2.0 descriptor set header (table 10) |
Troels Nilsson |
76:eef92651f52f | 56 | 0x0A, 0x00, // Header size (always 10 bytes) |
Troels Nilsson |
76:eef92651f52f | 57 | LSB(MS_OS_20_SET_HEADER_DESCRIPTOR), |
Troels Nilsson |
76:eef92651f52f | 58 | MSB(MS_OS_20_SET_HEADER_DESCRIPTOR), |
Troels Nilsson |
76:eef92651f52f | 59 | 0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000) |
Troels Nilsson |
76:eef92651f52f | 60 | LSB(MS_OS_20_DESCRIPTOR_LENGTH), |
Troels Nilsson |
76:eef92651f52f | 61 | MSB(MS_OS_20_DESCRIPTOR_LENGTH), |
Troels Nilsson |
76:eef92651f52f | 62 | |
Troels Nilsson |
76:eef92651f52f | 63 | // Configuration subset header (table 11) |
Troels Nilsson |
76:eef92651f52f | 64 | 0x08, 0x00, // wLength, always 8 |
Troels Nilsson |
76:eef92651f52f | 65 | LSB(MS_OS_20_SUBSET_HEADER_CONFIGURATION), |
Troels Nilsson |
76:eef92651f52f | 66 | MSB(MS_OS_20_SUBSET_HEADER_CONFIGURATION), |
Troels Nilsson |
76:eef92651f52f | 67 | 0x00, // "bConfigurationValue" - actually the index of the configuration, see https://social.msdn.microsoft.com/Forums/sqlserver/en-US/ae64282c-3bc3-49af-8391-4d174479d9e7/microsoft-os-20-descriptors-not-working-on-an-interface-of-a-composite-usb-device%3Fforum%3Dwdk+&cd=1&hl=da&ct=clnk&gl=dk&client=firefox-b |
Troels Nilsson |
76:eef92651f52f | 68 | 0x00, // reserved |
Troels Nilsson |
76:eef92651f52f | 69 | LSB(MS_OS_20_DESCRIPTOR_LENGTH - 10), // wTotalLength (length of subset including this header) |
Troels Nilsson |
76:eef92651f52f | 70 | MSB(MS_OS_20_DESCRIPTOR_LENGTH - 10), |
Troels Nilsson |
76:eef92651f52f | 71 | |
Troels Nilsson |
76:eef92651f52f | 72 | // Function subset (table 12) |
Troels Nilsson |
76:eef92651f52f | 73 | 0x08, 0x00, // wLength, always 8 |
Troels Nilsson |
76:eef92651f52f | 74 | LSB(MS_OS_20_SUBSET_HEADER_FUNCTION), |
Troels Nilsson |
76:eef92651f52f | 75 | MSB(MS_OS_20_SUBSET_HEADER_FUNCTION), |
Troels Nilsson |
76:eef92651f52f | 76 | 0x02, // bFirstInterface |
Troels Nilsson |
76:eef92651f52f | 77 | 0x00, // reserved |
Troels Nilsson |
76:eef92651f52f | 78 | LSB(MS_OS_20_DESCRIPTOR_LENGTH - 18), // wSubSetLength (length of subset including this header) |
Troels Nilsson |
76:eef92651f52f | 79 | MSB(MS_OS_20_DESCRIPTOR_LENGTH - 18), |
Troels Nilsson |
76:eef92651f52f | 80 | |
Troels Nilsson |
76:eef92651f52f | 81 | // Microsoft OS 2.0 compatible ID descriptor (table 13) |
Troels Nilsson |
76:eef92651f52f | 82 | // Ties the winusb driver to the webusb interface |
Troels Nilsson |
76:eef92651f52f | 83 | 0x14, 0x00, // wLength, always 20 |
Troels Nilsson |
76:eef92651f52f | 84 | LSB(MS_OS_20_FEATURE_COMPATIBLE_ID), |
Troels Nilsson |
76:eef92651f52f | 85 | MSB(MS_OS_20_FEATURE_COMPATIBLE_ID), |
Troels Nilsson |
76:eef92651f52f | 86 | 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // CompatibleID (string) |
Troels Nilsson |
76:eef92651f52f | 87 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // SubCompatibleID (string) |
Troels Nilsson |
76:eef92651f52f | 88 | |
Troels Nilsson |
76:eef92651f52f | 89 | // Registry property descriptor (table 14) |
Troels Nilsson |
76:eef92651f52f | 90 | // Sets a registry key named DeviceInterfaceGUIDs with a GUID for the WebUSB interface (apparently required before libusb can enumerate it...) |
Troels Nilsson |
76:eef92651f52f | 91 | 0x84, 0x00, // wLength (132) |
Troels Nilsson |
76:eef92651f52f | 92 | LSB(MS_OS_20_FEATURE_REG_PROPERTY), |
Troels Nilsson |
76:eef92651f52f | 93 | MSB(MS_OS_20_FEATURE_REG_PROPERTY), |
Troels Nilsson |
76:eef92651f52f | 94 | 0x07, 0x00, // wPropertyDataType (REG_MULTI_SZ) - see table 15 |
Troels Nilsson |
76:eef92651f52f | 95 | 0x2A, 0x00, // wPropertyNameLength (42) |
Troels Nilsson |
76:eef92651f52f | 96 | // Property name (wide string) : DeviceInterfaceGUIDs |
Troels Nilsson |
76:eef92651f52f | 97 | 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, 'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0, 'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0, |
Troels Nilsson |
76:eef92651f52f | 98 | 0x50, 0x00, // wPropertyDataLength (80) |
Troels Nilsson |
76:eef92651f52f | 99 | // Property data (wide string): {307A82E9-227E-48C3-8C4E-627BE96A7A78} (randomly generated for this device) |
Troels Nilsson |
76:eef92651f52f | 100 | '{', 0, '3', 0, '0', 0, '7', 0, 'A', 0, '8', 0, '2', 0, 'E', 0, '9', 0, '-', 0, |
Troels Nilsson |
76:eef92651f52f | 101 | '2', 0, '2', 0, '7', 0, 'E', 0, '-', 0, |
Troels Nilsson |
76:eef92651f52f | 102 | '4', 0, '8', 0, 'C', 0, '3', 0, '-', 0, |
Troels Nilsson |
76:eef92651f52f | 103 | '8', 0, 'C', 0, '4', 0, 'E', 0, '-', 0, |
Troels Nilsson |
76:eef92651f52f | 104 | '6', 0, '2', 0, '7', 0, 'B', 0, 'E', 0, '9', 0, '6', 0, 'A', 0, '7', 0, 'A', 0, '7', 0, '8', 0, '}', 0, 0, 0, 0, 0 |
Troels Nilsson |
76:eef92651f52f | 105 | }; |
Troels Nilsson |
76:eef92651f52f | 106 | |
Troels Nilsson |
76:eef92651f52f | 107 | |
Troels Nilsson |
76:eef92651f52f | 108 | USBWebUSBSerial::USBWebUSBSerial(uint16_t vendor_id, uint16_t product_id, uint16_t product_release, bool connect_blocking) |
Troels Nilsson |
76:eef92651f52f | 109 | : USBDevice(vendor_id, product_id, product_release) |
Troels Nilsson |
76:eef92651f52f | 110 | { |
Troels Nilsson |
76:eef92651f52f | 111 | m_terminalConnected = false; |
Troels Nilsson |
76:eef92651f52f | 112 | USBDevice::connect(connect_blocking); |
Troels Nilsson |
76:eef92651f52f | 113 | createDynamicDescriptors(); |
Troels Nilsson |
76:eef92651f52f | 114 | } |
Troels Nilsson |
76:eef92651f52f | 115 | |
Troels Nilsson |
78:ba3f68a86e6d | 116 | USBWebUSBSerial::~USBWebUSBSerial() |
Troels Nilsson |
78:ba3f68a86e6d | 117 | { |
Troels Nilsson |
78:ba3f68a86e6d | 118 | delete[] m_manufacturerStringDesc; |
Troels Nilsson |
78:ba3f68a86e6d | 119 | delete[] m_productStringDesc; |
Troels Nilsson |
78:ba3f68a86e6d | 120 | delete[] m_serialStringDesc; |
Troels Nilsson |
78:ba3f68a86e6d | 121 | } |
Troels Nilsson |
78:ba3f68a86e6d | 122 | |
Troels Nilsson |
76:eef92651f52f | 123 | void USBWebUSBSerial::USBCallback_busReset() |
Troels Nilsson |
76:eef92651f52f | 124 | { |
Troels Nilsson |
76:eef92651f52f | 125 | m_terminalConnected = false; |
Troels Nilsson |
77:a98f786d05d4 | 126 | m_pendingWrite = false; |
Troels Nilsson |
77:a98f786d05d4 | 127 | setWebUSBMode(false); |
Troels Nilsson |
76:eef92651f52f | 128 | } |
Troels Nilsson |
76:eef92651f52f | 129 | |
Troels Nilsson |
76:eef92651f52f | 130 | bool USBWebUSBSerial::USBCallback_request() |
Troels Nilsson |
76:eef92651f52f | 131 | { |
Troels Nilsson |
76:eef92651f52f | 132 | /* Called in ISR context */ |
Troels Nilsson |
76:eef92651f52f | 133 | |
Troels Nilsson |
76:eef92651f52f | 134 | bool success = false; |
Troels Nilsson |
76:eef92651f52f | 135 | CONTROL_TRANSFER * transfer = getTransferPtr(); |
Troels Nilsson |
76:eef92651f52f | 136 | |
Troels Nilsson |
76:eef92651f52f | 137 | /* Process class-specific requests */ |
Troels Nilsson |
76:eef92651f52f | 138 | if (transfer->setup.bmRequestType.Type == CLASS_TYPE) |
Troels Nilsson |
76:eef92651f52f | 139 | { |
Troels Nilsson |
76:eef92651f52f | 140 | switch (transfer->setup.bRequest) |
Troels Nilsson |
76:eef92651f52f | 141 | { |
Troels Nilsson |
76:eef92651f52f | 142 | case CDC_GET_LINE_CODING: |
Troels Nilsson |
76:eef92651f52f | 143 | transfer->remaining = 7; |
Troels Nilsson |
76:eef92651f52f | 144 | transfer->ptr = cdc_line_coding; |
Troels Nilsson |
76:eef92651f52f | 145 | transfer->direction = DEVICE_TO_HOST; |
Troels Nilsson |
76:eef92651f52f | 146 | success = true; |
Troels Nilsson |
76:eef92651f52f | 147 | break; |
Troels Nilsson |
76:eef92651f52f | 148 | case CDC_SET_LINE_CODING: |
Troels Nilsson |
76:eef92651f52f | 149 | transfer->remaining = 7; |
Troels Nilsson |
76:eef92651f52f | 150 | transfer->notify = true; |
Troels Nilsson |
76:eef92651f52f | 151 | success = true; |
Troels Nilsson |
76:eef92651f52f | 152 | break; |
Troels Nilsson |
76:eef92651f52f | 153 | case CDC_SET_CONTROL_LINE_STATE: |
Troels Nilsson |
76:eef92651f52f | 154 | if (transfer->setup.wValue & CLS_DTR) { |
Troels Nilsson |
76:eef92651f52f | 155 | m_terminalConnected = true; |
Troels Nilsson |
76:eef92651f52f | 156 | } else { |
Troels Nilsson |
76:eef92651f52f | 157 | m_terminalConnected = false; |
Troels Nilsson |
77:a98f786d05d4 | 158 | if (!m_webUSBMode) |
Troels Nilsson |
77:a98f786d05d4 | 159 | { |
Troels Nilsson |
77:a98f786d05d4 | 160 | m_pendingWrite = false; |
Troels Nilsson |
77:a98f786d05d4 | 161 | } |
Troels Nilsson |
76:eef92651f52f | 162 | } |
Troels Nilsson |
76:eef92651f52f | 163 | success = true; |
Troels Nilsson |
76:eef92651f52f | 164 | break; |
Troels Nilsson |
76:eef92651f52f | 165 | default: |
Troels Nilsson |
76:eef92651f52f | 166 | break; |
Troels Nilsson |
76:eef92651f52f | 167 | } |
Troels Nilsson |
76:eef92651f52f | 168 | } |
Troels Nilsson |
76:eef92651f52f | 169 | else if (transfer->setup.bmRequestType.Type == VENDOR_TYPE && transfer->setup.bRequest == WINUSB_VENDOR_CODE && transfer->setup.wIndex == MS_OS_20_DESCRIPTOR_INDEX) |
Troels Nilsson |
76:eef92651f52f | 170 | { |
Troels Nilsson |
76:eef92651f52f | 171 | // Request for the MS OS 2.0 descriptor |
Troels Nilsson |
76:eef92651f52f | 172 | transfer->remaining = MS_OS_20_DESCRIPTOR_LENGTH; |
Troels Nilsson |
76:eef92651f52f | 173 | transfer->ptr = s_MSOS2Descriptor; |
Troels Nilsson |
76:eef92651f52f | 174 | transfer->direction = DEVICE_TO_HOST; |
Troels Nilsson |
76:eef92651f52f | 175 | success = true; |
Troels Nilsson |
76:eef92651f52f | 176 | } |
Troels Nilsson |
76:eef92651f52f | 177 | else if (transfer->setup.bmRequestType.Type == VENDOR_TYPE && transfer->setup.bRequest == SET_WEBUSB_ACTIVE_VENDOR_CODE) |
Troels Nilsson |
76:eef92651f52f | 178 | { |
Troels Nilsson |
76:eef92651f52f | 179 | if (transfer->setup.wValue == 0) |
Troels Nilsson |
76:eef92651f52f | 180 | { |
Troels Nilsson |
76:eef92651f52f | 181 | // Disable WebUSB mode |
Troels Nilsson |
77:a98f786d05d4 | 182 | setWebUSBMode(false); |
Troels Nilsson |
76:eef92651f52f | 183 | } |
Troels Nilsson |
76:eef92651f52f | 184 | else |
Troels Nilsson |
76:eef92651f52f | 185 | { |
Troels Nilsson |
76:eef92651f52f | 186 | // Enable WebUSB mode |
Troels Nilsson |
77:a98f786d05d4 | 187 | setWebUSBMode(true); |
Troels Nilsson |
76:eef92651f52f | 188 | } |
Troels Nilsson |
76:eef92651f52f | 189 | success = true; |
Troels Nilsson |
76:eef92651f52f | 190 | } |
Troels Nilsson |
76:eef92651f52f | 191 | |
Troels Nilsson |
76:eef92651f52f | 192 | return success; |
Troels Nilsson |
76:eef92651f52f | 193 | } |
Troels Nilsson |
76:eef92651f52f | 194 | |
Troels Nilsson |
76:eef92651f52f | 195 | void USBWebUSBSerial::USBCallback_requestCompleted(uint8_t *buf, uint32_t length) |
Troels Nilsson |
76:eef92651f52f | 196 | { |
Troels Nilsson |
76:eef92651f52f | 197 | // Request of setting line coding has 7 bytes |
Troels Nilsson |
76:eef92651f52f | 198 | if (length != 7) |
Troels Nilsson |
76:eef92651f52f | 199 | { |
Troels Nilsson |
76:eef92651f52f | 200 | return; |
Troels Nilsson |
76:eef92651f52f | 201 | } |
Troels Nilsson |
76:eef92651f52f | 202 | |
Troels Nilsson |
76:eef92651f52f | 203 | CONTROL_TRANSFER * transfer = getTransferPtr(); |
Troels Nilsson |
76:eef92651f52f | 204 | |
Troels Nilsson |
76:eef92651f52f | 205 | /* Process class-specific requests */ |
Troels Nilsson |
76:eef92651f52f | 206 | if (transfer->setup.bmRequestType.Type == CLASS_TYPE) |
Troels Nilsson |
76:eef92651f52f | 207 | { |
Troels Nilsson |
76:eef92651f52f | 208 | if (transfer->setup.bRequest == CDC_SET_LINE_CODING) |
Troels Nilsson |
76:eef92651f52f | 209 | { |
Troels Nilsson |
76:eef92651f52f | 210 | if (memcmp(cdc_line_coding, buf, 7)) |
Troels Nilsson |
76:eef92651f52f | 211 | { |
Troels Nilsson |
76:eef92651f52f | 212 | memcpy(cdc_line_coding, buf, 7); |
Troels Nilsson |
76:eef92651f52f | 213 | |
Troels Nilsson |
76:eef92651f52f | 214 | int baud = buf[0] + (buf[1] << 8) |
Troels Nilsson |
76:eef92651f52f | 215 | + (buf[2] << 16) + (buf[3] << 24); |
Troels Nilsson |
76:eef92651f52f | 216 | int stop = buf[4]; |
Troels Nilsson |
76:eef92651f52f | 217 | int bits = buf[6]; |
Troels Nilsson |
76:eef92651f52f | 218 | int parity = buf[5]; |
Troels Nilsson |
76:eef92651f52f | 219 | |
Troels Nilsson |
76:eef92651f52f | 220 | lineCodingChanged(baud, bits, parity, stop); |
Troels Nilsson |
76:eef92651f52f | 221 | } |
Troels Nilsson |
76:eef92651f52f | 222 | } |
Troels Nilsson |
76:eef92651f52f | 223 | } |
Troels Nilsson |
76:eef92651f52f | 224 | } |
Troels Nilsson |
76:eef92651f52f | 225 | |
Troels Nilsson |
76:eef92651f52f | 226 | // Called in ISR context |
Troels Nilsson |
76:eef92651f52f | 227 | // Set configuration. Return false if the |
Troels Nilsson |
76:eef92651f52f | 228 | // configuration is not supported. |
Troels Nilsson |
76:eef92651f52f | 229 | bool USBWebUSBSerial::USBCallback_setConfiguration(uint8_t configuration) |
Troels Nilsson |
76:eef92651f52f | 230 | { |
Troels Nilsson |
76:eef92651f52f | 231 | if (configuration != DEFAULT_CONFIGURATION) |
Troels Nilsson |
76:eef92651f52f | 232 | { |
Troels Nilsson |
76:eef92651f52f | 233 | return false; |
Troels Nilsson |
76:eef92651f52f | 234 | } |
Troels Nilsson |
76:eef92651f52f | 235 | |
Troels Nilsson |
76:eef92651f52f | 236 | if (configured()) |
Troels Nilsson |
76:eef92651f52f | 237 | { |
Troels Nilsson |
76:eef92651f52f | 238 | // Already configured, nothing to do |
Troels Nilsson |
76:eef92651f52f | 239 | return true; |
Troels Nilsson |
76:eef92651f52f | 240 | } |
Troels Nilsson |
76:eef92651f52f | 241 | |
Troels Nilsson |
76:eef92651f52f | 242 | // Configure endpoints > 0 |
Troels Nilsson |
76:eef92651f52f | 243 | addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT); |
Troels Nilsson |
76:eef92651f52f | 244 | addEndpoint(EPCDC_IN, MAX_PACKET_SIZE_EPBULK); |
Troels Nilsson |
76:eef92651f52f | 245 | addEndpoint(EPCDC_OUT, MAX_PACKET_SIZE_EPBULK); |
Troels Nilsson |
76:eef92651f52f | 246 | addEndpoint(EPWEBUSB_IN, MAX_PACKET_SIZE_EPBULK); |
Troels Nilsson |
76:eef92651f52f | 247 | addEndpoint(EPWEBUSB_OUT, MAX_PACKET_SIZE_EPBULK); |
Troels Nilsson |
76:eef92651f52f | 248 | |
Troels Nilsson |
76:eef92651f52f | 249 | // We activate the endpoints to be able to receive data |
Troels Nilsson |
76:eef92651f52f | 250 | readStart(EPCDC_OUT, MAX_PACKET_SIZE_EPBULK); |
Troels Nilsson |
76:eef92651f52f | 251 | readStart(EPWEBUSB_OUT, MAX_PACKET_SIZE_EPBULK); |
Troels Nilsson |
76:eef92651f52f | 252 | return true; |
Troels Nilsson |
76:eef92651f52f | 253 | } |
Troels Nilsson |
76:eef92651f52f | 254 | |
Troels Nilsson |
77:a98f786d05d4 | 255 | void USBWebUSBSerial::writeToActiveEndpoint() |
Troels Nilsson |
76:eef92651f52f | 256 | { |
Troels Nilsson |
77:a98f786d05d4 | 257 | CriticalSectionLock lock; |
Troels Nilsson |
77:a98f786d05d4 | 258 | if(!configured() || m_outputBuffer.isEmpty()) |
Troels Nilsson |
76:eef92651f52f | 259 | { |
Troels Nilsson |
77:a98f786d05d4 | 260 | m_pendingWrite = false; |
Troels Nilsson |
77:a98f786d05d4 | 261 | return; |
Troels Nilsson |
77:a98f786d05d4 | 262 | } |
Troels Nilsson |
76:eef92651f52f | 263 | |
Troels Nilsson |
77:a98f786d05d4 | 264 | uint8_t buffer[MAX_PACKET_SIZE_EPBULK]; |
Troels Nilsson |
77:a98f786d05d4 | 265 | uint16_t size = m_outputBuffer.dequeue(buffer, MAX_PACKET_SIZE_EPBULK); |
Troels Nilsson |
76:eef92651f52f | 266 | |
Troels Nilsson |
77:a98f786d05d4 | 267 | EP_STATUS result = endpointWrite(activeInEndpoint(), buffer, size); |
Troels Nilsson |
76:eef92651f52f | 268 | |
Troels Nilsson |
77:a98f786d05d4 | 269 | if (result != EP_PENDING) |
Troels Nilsson |
77:a98f786d05d4 | 270 | { |
Troels Nilsson |
77:a98f786d05d4 | 271 | return; |
Troels Nilsson |
77:a98f786d05d4 | 272 | } |
Troels Nilsson |
76:eef92651f52f | 273 | |
Troels Nilsson |
77:a98f786d05d4 | 274 | m_lastWriteTime = osKernelGetTickCount(); |
Troels Nilsson |
77:a98f786d05d4 | 275 | m_pendingWrite = true; |
Troels Nilsson |
76:eef92651f52f | 276 | } |
Troels Nilsson |
76:eef92651f52f | 277 | |
Troels Nilsson |
76:eef92651f52f | 278 | bool USBWebUSBSerial::readActiveEP() |
Troels Nilsson |
76:eef92651f52f | 279 | { |
Troels Nilsson |
77:a98f786d05d4 | 280 | CriticalSectionLock lock; |
Troels Nilsson |
76:eef92651f52f | 281 | uint8_t buffer[MAX_PACKET_SIZE_EPBULK]; |
Troels Nilsson |
76:eef92651f52f | 282 | uint32_t size = 0; |
Troels Nilsson |
76:eef92651f52f | 283 | if (!USBDevice::readEP_NB(activeOutEndpoint(), buffer, &size, MAX_PACKET_SIZE_EPBULK)) |
Troels Nilsson |
76:eef92651f52f | 284 | { |
Troels Nilsson |
76:eef92651f52f | 285 | return false; |
Troels Nilsson |
76:eef92651f52f | 286 | } |
Troels Nilsson |
76:eef92651f52f | 287 | if (!readStart(activeOutEndpoint(), MAX_PACKET_SIZE_EPBULK)) |
Troels Nilsson |
76:eef92651f52f | 288 | { |
Troels Nilsson |
76:eef92651f52f | 289 | return false; |
Troels Nilsson |
76:eef92651f52f | 290 | } |
Troels Nilsson |
76:eef92651f52f | 291 | |
Troels Nilsson |
77:a98f786d05d4 | 292 | m_inputBuffer.queue(buffer, size); |
Troels Nilsson |
76:eef92651f52f | 293 | |
Troels Nilsson |
76:eef92651f52f | 294 | if (size != 0 && activeOutEndpoint() == EPCDC_OUT) |
Troels Nilsson |
76:eef92651f52f | 295 | { |
Troels Nilsson |
76:eef92651f52f | 296 | // terminal must be connected now since we received packets |
Troels Nilsson |
76:eef92651f52f | 297 | m_terminalConnected = true; |
Troels Nilsson |
76:eef92651f52f | 298 | } |
Troels Nilsson |
76:eef92651f52f | 299 | |
Troels Nilsson |
76:eef92651f52f | 300 | // call a potential handler |
Troels Nilsson |
76:eef92651f52f | 301 | if (m_rx) |
Troels Nilsson |
76:eef92651f52f | 302 | { |
Troels Nilsson |
76:eef92651f52f | 303 | m_rx.call(); |
Troels Nilsson |
76:eef92651f52f | 304 | } |
Troels Nilsson |
76:eef92651f52f | 305 | |
Troels Nilsson |
76:eef92651f52f | 306 | return true; |
Troels Nilsson |
76:eef92651f52f | 307 | } |
Troels Nilsson |
76:eef92651f52f | 308 | |
Troels Nilsson |
76:eef92651f52f | 309 | uint8_t * USBWebUSBSerial::deviceDesc() |
Troels Nilsson |
76:eef92651f52f | 310 | { |
Troels Nilsson |
76:eef92651f52f | 311 | static uint8_t deviceDescriptor[] = { |
Troels Nilsson |
76:eef92651f52f | 312 | DEVICE_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 313 | DEVICE_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 314 | 0x10, 0x02, // bcdUSB = 2.10 |
Troels Nilsson |
76:eef92651f52f | 315 | 0, // bDeviceClass: composite (unspecified on device level) |
Troels Nilsson |
76:eef92651f52f | 316 | 0, // bDeviceSubClass |
Troels Nilsson |
76:eef92651f52f | 317 | 0, // bDeviceProtocol |
Troels Nilsson |
76:eef92651f52f | 318 | MAX_PACKET_SIZE_EP0, // bMaxPacketSize0 |
Troels Nilsson |
76:eef92651f52f | 319 | (uint8_t)(LSB(VENDOR_ID)), (uint8_t)(MSB(VENDOR_ID)), // idVendor |
Troels Nilsson |
76:eef92651f52f | 320 | (uint8_t)(LSB(PRODUCT_ID)), (uint8_t)(MSB(PRODUCT_ID)),// idProduct |
Troels Nilsson |
76:eef92651f52f | 321 | 0x00, 0x01, // bcdDevice |
Troels Nilsson |
76:eef92651f52f | 322 | STRING_OFFSET_IMANUFACTURER, // iManufacturer |
Troels Nilsson |
76:eef92651f52f | 323 | STRING_OFFSET_IPRODUCT, // iProduct |
Troels Nilsson |
76:eef92651f52f | 324 | STRING_OFFSET_ISERIAL, // iSerialNumber |
Troels Nilsson |
76:eef92651f52f | 325 | 1 // bNumConfigurations |
Troels Nilsson |
76:eef92651f52f | 326 | }; |
Troels Nilsson |
76:eef92651f52f | 327 | return deviceDescriptor; |
Troels Nilsson |
76:eef92651f52f | 328 | } |
Troels Nilsson |
76:eef92651f52f | 329 | |
Troels Nilsson |
76:eef92651f52f | 330 | uint8_t * USBWebUSBSerial::stringImanufacturerDesc() |
Troels Nilsson |
76:eef92651f52f | 331 | { |
Troels Nilsson |
76:eef92651f52f | 332 | return m_manufacturerStringDesc; |
Troels Nilsson |
76:eef92651f52f | 333 | } |
Troels Nilsson |
76:eef92651f52f | 334 | |
Troels Nilsson |
76:eef92651f52f | 335 | uint8_t * USBWebUSBSerial::stringIproductDesc() |
Troels Nilsson |
76:eef92651f52f | 336 | { |
Troels Nilsson |
76:eef92651f52f | 337 | return m_productStringDesc; |
Troels Nilsson |
76:eef92651f52f | 338 | } |
Troels Nilsson |
76:eef92651f52f | 339 | |
Troels Nilsson |
76:eef92651f52f | 340 | uint8_t * USBWebUSBSerial::stringIserialDesc() |
Troels Nilsson |
76:eef92651f52f | 341 | { |
Troels Nilsson |
76:eef92651f52f | 342 | return m_serialStringDesc; |
Troels Nilsson |
76:eef92651f52f | 343 | } |
Troels Nilsson |
76:eef92651f52f | 344 | |
Troels Nilsson |
76:eef92651f52f | 345 | #define CONFIG1_DESC_SIZE (CONFIGURATION_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 346 | INTERFACE_ASSOCIATION_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 347 | INTERFACE_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 348 | 5+5+4+5 + \ |
Troels Nilsson |
76:eef92651f52f | 349 | ENDPOINT_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 350 | INTERFACE_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 351 | ENDPOINT_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 352 | ENDPOINT_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 353 | INTERFACE_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 354 | ENDPOINT_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 355 | ENDPOINT_DESCRIPTOR_LENGTH) |
Troels Nilsson |
76:eef92651f52f | 356 | |
Troels Nilsson |
76:eef92651f52f | 357 | uint8_t * USBWebUSBSerial::configurationDesc() |
Troels Nilsson |
76:eef92651f52f | 358 | { |
Troels Nilsson |
76:eef92651f52f | 359 | static uint8_t configDescriptor[] = { |
Troels Nilsson |
76:eef92651f52f | 360 | // configuration descriptor |
Troels Nilsson |
76:eef92651f52f | 361 | CONFIGURATION_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 362 | CONFIGURATION_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 363 | LSB(CONFIG1_DESC_SIZE), // wTotalLength |
Troels Nilsson |
76:eef92651f52f | 364 | MSB(CONFIG1_DESC_SIZE), |
Troels Nilsson |
76:eef92651f52f | 365 | 3, // bNumInterfaces |
Troels Nilsson |
76:eef92651f52f | 366 | 1, // bConfigurationValue |
Troels Nilsson |
76:eef92651f52f | 367 | 0, // iConfiguration |
Troels Nilsson |
76:eef92651f52f | 368 | 0x80, // bmAttributes |
Troels Nilsson |
76:eef92651f52f | 369 | 50, // bMaxPower |
Troels Nilsson |
76:eef92651f52f | 370 | |
Troels Nilsson |
76:eef92651f52f | 371 | // IAD to associate the two CDC interfaces |
Troels Nilsson |
76:eef92651f52f | 372 | INTERFACE_ASSOCIATION_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 373 | INTERFACE_ASSOCIATION_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 374 | 0x00, // bFirstInterface |
Troels Nilsson |
76:eef92651f52f | 375 | 0x02, // bInterfaceCount |
Troels Nilsson |
76:eef92651f52f | 376 | USB_CDC_CLASS, // bFunctionClass |
Troels Nilsson |
76:eef92651f52f | 377 | USB_ACM_SUBCLASS, // bFunctionSubClass |
Troels Nilsson |
76:eef92651f52f | 378 | 0, // bFunctionProtocol |
Troels Nilsson |
76:eef92651f52f | 379 | 0, // iFunction |
Troels Nilsson |
76:eef92651f52f | 380 | |
Troels Nilsson |
76:eef92651f52f | 381 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 |
Troels Nilsson |
76:eef92651f52f | 382 | INTERFACE_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 383 | INTERFACE_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 384 | 0, // bInterfaceNumber |
Troels Nilsson |
76:eef92651f52f | 385 | 0, // bAlternateSetting |
Troels Nilsson |
76:eef92651f52f | 386 | 1, // bNumEndpoints |
Troels Nilsson |
76:eef92651f52f | 387 | USB_CDC_CLASS, // bInterfaceClass |
Troels Nilsson |
76:eef92651f52f | 388 | USB_ACM_SUBCLASS, // bInterfaceSubClass |
Troels Nilsson |
76:eef92651f52f | 389 | 0x01, // bInterfaceProtocol |
Troels Nilsson |
76:eef92651f52f | 390 | 0, // iInterface |
Troels Nilsson |
76:eef92651f52f | 391 | |
Troels Nilsson |
76:eef92651f52f | 392 | // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 |
Troels Nilsson |
76:eef92651f52f | 393 | 5, // bFunctionLength |
Troels Nilsson |
76:eef92651f52f | 394 | USB_CS_INTERFACE, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 395 | USB_HEADER_FUNCTION_DESCRIPTOR_TYPE, // bDescriptorSubtype |
Troels Nilsson |
76:eef92651f52f | 396 | 0x10, 0x01, // bcdCDC |
Troels Nilsson |
76:eef92651f52f | 397 | |
Troels Nilsson |
76:eef92651f52f | 398 | // Call Management Functional Descriptor, CDC PSTN Spec 5.3.1, Table 3 |
Troels Nilsson |
76:eef92651f52f | 399 | 5, // bFunctionLength |
Troels Nilsson |
76:eef92651f52f | 400 | USB_CS_INTERFACE, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 401 | USB_CALL_MANAGEMENT_FUNCTION_DESCRIPTOR_TYPE, // bDescriptorSubtype |
Troels Nilsson |
76:eef92651f52f | 402 | 0x03, // bmCapabilities |
Troels Nilsson |
76:eef92651f52f | 403 | 1, // bDataInterface |
Troels Nilsson |
76:eef92651f52f | 404 | |
Troels Nilsson |
76:eef92651f52f | 405 | // Abstract Control Management Functional Descriptor, CDC PSTN Spec 5.3.2, Table 4 |
Troels Nilsson |
76:eef92651f52f | 406 | 4, // bFunctionLength |
Troels Nilsson |
76:eef92651f52f | 407 | USB_CS_INTERFACE, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 408 | USB_ABSTRACT_CONTROL_MANAGEMENT_FUNCTION_DESCRIPTOR_TYPE, // bDescriptorSubtype |
Troels Nilsson |
76:eef92651f52f | 409 | 0x06, // bmCapabilities |
Troels Nilsson |
76:eef92651f52f | 410 | |
Troels Nilsson |
76:eef92651f52f | 411 | // Union Functional Descriptor, CDC Spec 5.2.3.2, Table 16 |
Troels Nilsson |
76:eef92651f52f | 412 | 5, // bFunctionLength |
Troels Nilsson |
76:eef92651f52f | 413 | USB_CS_INTERFACE, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 414 | USB_UNION_INTERFACE_FUNCTION_DESCRIPTOR_TYPE, // bDescriptorSubtype |
Troels Nilsson |
76:eef92651f52f | 415 | 0, // bMasterInterface |
Troels Nilsson |
76:eef92651f52f | 416 | 1, // bSlaveInterface0 |
Troels Nilsson |
76:eef92651f52f | 417 | |
Troels Nilsson |
76:eef92651f52f | 418 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 |
Troels Nilsson |
76:eef92651f52f | 419 | ENDPOINT_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 420 | ENDPOINT_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 421 | PHY_TO_DESC(EPINT_IN), // bEndpointAddress |
Troels Nilsson |
76:eef92651f52f | 422 | E_INTERRUPT, // bmAttributes (0x03=intr) |
Troels Nilsson |
76:eef92651f52f | 423 | LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) |
Troels Nilsson |
76:eef92651f52f | 424 | MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) |
Troels Nilsson |
76:eef92651f52f | 425 | 16, // bInterval |
Troels Nilsson |
76:eef92651f52f | 426 | |
Troels Nilsson |
76:eef92651f52f | 427 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 |
Troels Nilsson |
76:eef92651f52f | 428 | INTERFACE_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 429 | INTERFACE_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 430 | 1, // bInterfaceNumber |
Troels Nilsson |
76:eef92651f52f | 431 | 0, // bAlternateSetting |
Troels Nilsson |
76:eef92651f52f | 432 | 2, // bNumEndpoints |
Troels Nilsson |
76:eef92651f52f | 433 | USB_CDC_DATA_CLASS, // bInterfaceClass |
Troels Nilsson |
76:eef92651f52f | 434 | 0x00, // bInterfaceSubClass |
Troels Nilsson |
76:eef92651f52f | 435 | 0x00, // bInterfaceProtocol |
Troels Nilsson |
76:eef92651f52f | 436 | 0, // iInterface |
Troels Nilsson |
76:eef92651f52f | 437 | |
Troels Nilsson |
76:eef92651f52f | 438 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 |
Troels Nilsson |
76:eef92651f52f | 439 | ENDPOINT_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 440 | ENDPOINT_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 441 | PHY_TO_DESC(EPCDC_IN), // bEndpointAddress |
Troels Nilsson |
76:eef92651f52f | 442 | E_BULK, // bmAttributes (0x02=bulk) |
Troels Nilsson |
76:eef92651f52f | 443 | LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) |
Troels Nilsson |
76:eef92651f52f | 444 | MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) |
Troels Nilsson |
76:eef92651f52f | 445 | 0, // bInterval |
Troels Nilsson |
76:eef92651f52f | 446 | |
Troels Nilsson |
76:eef92651f52f | 447 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 |
Troels Nilsson |
76:eef92651f52f | 448 | ENDPOINT_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 449 | ENDPOINT_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 450 | PHY_TO_DESC(EPCDC_OUT), // bEndpointAddress |
Troels Nilsson |
76:eef92651f52f | 451 | E_BULK, // bmAttributes (0x02=bulk) |
Troels Nilsson |
76:eef92651f52f | 452 | LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) |
Troels Nilsson |
76:eef92651f52f | 453 | MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) |
Troels Nilsson |
76:eef92651f52f | 454 | 0, // bInterval |
Troels Nilsson |
76:eef92651f52f | 455 | |
Troels Nilsson |
76:eef92651f52f | 456 | // WebUSB interface |
Troels Nilsson |
76:eef92651f52f | 457 | INTERFACE_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 458 | INTERFACE_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 459 | 2, // bInterfaceNumber |
Troels Nilsson |
76:eef92651f52f | 460 | 0, // bAlternateSetting |
Troels Nilsson |
76:eef92651f52f | 461 | 2, // bNumEndpoints |
Troels Nilsson |
76:eef92651f52f | 462 | USB_CUSTOM_CLASS, // bInterfaceClass |
Troels Nilsson |
76:eef92651f52f | 463 | 0x00, // bInterfaceSubClass |
Troels Nilsson |
76:eef92651f52f | 464 | 0x00, // bInterfaceProtocol |
Troels Nilsson |
76:eef92651f52f | 465 | 0, // iInterface |
Troels Nilsson |
76:eef92651f52f | 466 | |
Troels Nilsson |
76:eef92651f52f | 467 | // WebUSB IN endpoint |
Troels Nilsson |
76:eef92651f52f | 468 | ENDPOINT_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 469 | ENDPOINT_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 470 | PHY_TO_DESC(EPWEBUSB_IN), // bEndpointAddress |
Troels Nilsson |
76:eef92651f52f | 471 | E_BULK, // bmAttributes (0x02=bulk) |
Troels Nilsson |
76:eef92651f52f | 472 | LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) |
Troels Nilsson |
76:eef92651f52f | 473 | MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) |
Troels Nilsson |
76:eef92651f52f | 474 | 0, // bInterval |
Troels Nilsson |
76:eef92651f52f | 475 | |
Troels Nilsson |
76:eef92651f52f | 476 | // WebUSB OUT endpoint |
Troels Nilsson |
76:eef92651f52f | 477 | ENDPOINT_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 478 | ENDPOINT_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 479 | PHY_TO_DESC(EPWEBUSB_OUT), // bEndpointAddress |
Troels Nilsson |
76:eef92651f52f | 480 | E_BULK, // bmAttributes (0x02=bulk) |
Troels Nilsson |
76:eef92651f52f | 481 | LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) |
Troels Nilsson |
76:eef92651f52f | 482 | MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) |
Troels Nilsson |
76:eef92651f52f | 483 | 0 // bInterval |
Troels Nilsson |
76:eef92651f52f | 484 | }; |
Troels Nilsson |
76:eef92651f52f | 485 | return configDescriptor; |
Troels Nilsson |
76:eef92651f52f | 486 | } |
Troels Nilsson |
76:eef92651f52f | 487 | |
Troels Nilsson |
76:eef92651f52f | 488 | #define BOS_MSOS2_PLATFORM_DESCRIPTOR_LENGTH 28 |
Troels Nilsson |
76:eef92651f52f | 489 | #define BOS_TOTAL_LENGTH (BOS_DESCRIPTOR_LENGTH + BOS_MSOS2_PLATFORM_DESCRIPTOR_LENGTH) |
Troels Nilsson |
76:eef92651f52f | 490 | |
Troels Nilsson |
76:eef92651f52f | 491 | uint8_t * USBWebUSBSerial::bosDesc() |
Troels Nilsson |
76:eef92651f52f | 492 | { |
Troels Nilsson |
76:eef92651f52f | 493 | static uint8_t bosDescriptor[] = { |
Troels Nilsson |
76:eef92651f52f | 494 | BOS_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 495 | BOS_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 496 | LSB(BOS_TOTAL_LENGTH), // wTotalLength (LSB) |
Troels Nilsson |
76:eef92651f52f | 497 | MSB(BOS_TOTAL_LENGTH), // wTotalLength (MSB) |
Troels Nilsson |
76:eef92651f52f | 498 | 0x01, // bNumDeviceCaps |
Troels Nilsson |
76:eef92651f52f | 499 | |
Troels Nilsson |
76:eef92651f52f | 500 | // MS OS 2.0 descriptors information |
Troels Nilsson |
76:eef92651f52f | 501 | BOS_MSOS2_PLATFORM_DESCRIPTOR_LENGTH, |
Troels Nilsson |
76:eef92651f52f | 502 | DEVICE_CAPABILITY_DESCRIPTOR, |
Troels Nilsson |
76:eef92651f52f | 503 | PLATFORM_DEVICE_CAPABILITY_TYPE, |
Troels Nilsson |
76:eef92651f52f | 504 | 0x00, // bReserved |
Troels Nilsson |
76:eef92651f52f | 505 | 0xDF, 0x60, 0xDD, 0xD8, // PlatformCapabilityUUID ({D8DD60DF-4589-4CC7-9CD2-659D9E648A9F}) |
Troels Nilsson |
76:eef92651f52f | 506 | 0x89, 0x45, |
Troels Nilsson |
76:eef92651f52f | 507 | 0xC7, 0x4C, |
Troels Nilsson |
76:eef92651f52f | 508 | 0x9C, 0xD2, |
Troels Nilsson |
76:eef92651f52f | 509 | 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F, |
Troels Nilsson |
76:eef92651f52f | 510 | |
Troels Nilsson |
76:eef92651f52f | 511 | 0x00, 0x00, 0x03, 0x06, // Windows version (8.1 = 0x06030000) |
Troels Nilsson |
76:eef92651f52f | 512 | LSB(MS_OS_20_DESCRIPTOR_LENGTH), // wMSOSDecriptorSetTotalLength (LSB) |
Troels Nilsson |
76:eef92651f52f | 513 | MSB(MS_OS_20_DESCRIPTOR_LENGTH), // wMSOSDecriptorSetTotalLength (MSB) |
Troels Nilsson |
76:eef92651f52f | 514 | WINUSB_VENDOR_CODE, // bMS_VendorCode |
Troels Nilsson |
76:eef92651f52f | 515 | 0x00 // bAltEnum |
Troels Nilsson |
76:eef92651f52f | 516 | }; |
Troels Nilsson |
76:eef92651f52f | 517 | return bosDescriptor; |
Troels Nilsson |
76:eef92651f52f | 518 | } |
Troels Nilsson |
76:eef92651f52f | 519 | |
Troels Nilsson |
78:ba3f68a86e6d | 520 | int USBWebUSBSerial::read(uint8_t *buf, uint16_t size) |
Troels Nilsson |
76:eef92651f52f | 521 | { |
Troels Nilsson |
77:a98f786d05d4 | 522 | CriticalSectionLock lock; |
Troels Nilsson |
78:ba3f68a86e6d | 523 | return m_inputBuffer.dequeue(buf, size); |
Troels Nilsson |
76:eef92651f52f | 524 | } |
Troels Nilsson |
76:eef92651f52f | 525 | |
Troels Nilsson |
77:a98f786d05d4 | 526 | bool USBWebUSBSerial::writeBuffered(const uint8_t * buf, uint16_t size) |
Troels Nilsson |
76:eef92651f52f | 527 | { |
Troels Nilsson |
77:a98f786d05d4 | 528 | CriticalSectionLock lock; |
Troels Nilsson |
76:eef92651f52f | 529 | if(!m_terminalConnected && !m_webUSBMode) |
Troels Nilsson |
76:eef92651f52f | 530 | { |
Troels Nilsson |
76:eef92651f52f | 531 | return false; |
Troels Nilsson |
76:eef92651f52f | 532 | } |
Troels Nilsson |
77:a98f786d05d4 | 533 | |
Troels Nilsson |
77:a98f786d05d4 | 534 | m_outputBuffer.queue(buf, size); |
Troels Nilsson |
77:a98f786d05d4 | 535 | if (!m_pendingWrite) |
Troels Nilsson |
76:eef92651f52f | 536 | { |
Troels Nilsson |
77:a98f786d05d4 | 537 | writeToActiveEndpoint(); |
Troels Nilsson |
76:eef92651f52f | 538 | } |
Troels Nilsson |
77:a98f786d05d4 | 539 | else if (m_webUSBMode) |
Troels Nilsson |
76:eef92651f52f | 540 | { |
Troels Nilsson |
77:a98f786d05d4 | 541 | // Check if the write has timed out |
Troels Nilsson |
77:a98f786d05d4 | 542 | if (timeSinceWrite() > WEBUSB_WRITE_TIMEOUT) |
Troels Nilsson |
77:a98f786d05d4 | 543 | { |
Troels Nilsson |
77:a98f786d05d4 | 544 | // Host is no longer reading WebUSB endpoint, assume the client is gone and go back to CDC mode |
Troels Nilsson |
77:a98f786d05d4 | 545 | setWebUSBMode(false); |
Troels Nilsson |
77:a98f786d05d4 | 546 | } |
Troels Nilsson |
76:eef92651f52f | 547 | } |
Troels Nilsson |
77:a98f786d05d4 | 548 | |
Troels Nilsson |
76:eef92651f52f | 549 | return true; |
Troels Nilsson |
76:eef92651f52f | 550 | } |
Troels Nilsson |
76:eef92651f52f | 551 | |
Troels Nilsson |
76:eef92651f52f | 552 | bool USBWebUSBSerial::EPCDC_OUT_callback() |
Troels Nilsson |
76:eef92651f52f | 553 | { |
Troels Nilsson |
76:eef92651f52f | 554 | EPOUTCallbackHandler(EPCDC_OUT); |
Troels Nilsson |
76:eef92651f52f | 555 | return true; |
Troels Nilsson |
76:eef92651f52f | 556 | } |
Troels Nilsson |
76:eef92651f52f | 557 | |
Troels Nilsson |
76:eef92651f52f | 558 | bool USBWebUSBSerial::EPWEBUSB_OUT_callback() |
Troels Nilsson |
76:eef92651f52f | 559 | { |
Troels Nilsson |
76:eef92651f52f | 560 | EPOUTCallbackHandler(EPWEBUSB_OUT); |
Troels Nilsson |
76:eef92651f52f | 561 | return true; |
Troels Nilsson |
76:eef92651f52f | 562 | } |
Troels Nilsson |
76:eef92651f52f | 563 | |
Troels Nilsson |
76:eef92651f52f | 564 | bool USBWebUSBSerial::EPOUTCallbackHandler(uint8_t endpoint) |
Troels Nilsson |
76:eef92651f52f | 565 | { |
Troels Nilsson |
77:a98f786d05d4 | 566 | CriticalSectionLock lock; |
Troels Nilsson |
76:eef92651f52f | 567 | if (endpoint == activeOutEndpoint()) |
Troels Nilsson |
76:eef92651f52f | 568 | { |
Troels Nilsson |
76:eef92651f52f | 569 | return readActiveEP(); |
Troels Nilsson |
76:eef92651f52f | 570 | } |
Troels Nilsson |
76:eef92651f52f | 571 | else |
Troels Nilsson |
76:eef92651f52f | 572 | { |
Troels Nilsson |
76:eef92651f52f | 573 | // Read out the data but ignore it since it is on the inactive endpoint |
Troels Nilsson |
76:eef92651f52f | 574 | uint8_t buffer[MAX_PACKET_SIZE_EPBULK]; |
Troels Nilsson |
76:eef92651f52f | 575 | uint32_t size = 0; |
Troels Nilsson |
76:eef92651f52f | 576 | if (!USBDevice::readEP_NB(endpoint, buffer, &size, MAX_PACKET_SIZE_EPBULK)) |
Troels Nilsson |
76:eef92651f52f | 577 | { |
Troels Nilsson |
76:eef92651f52f | 578 | return false; |
Troels Nilsson |
76:eef92651f52f | 579 | } |
Troels Nilsson |
76:eef92651f52f | 580 | if (!readStart(endpoint, MAX_PACKET_SIZE_EPBULK)) |
Troels Nilsson |
76:eef92651f52f | 581 | { |
Troels Nilsson |
76:eef92651f52f | 582 | return false; |
Troels Nilsson |
76:eef92651f52f | 583 | } |
Troels Nilsson |
76:eef92651f52f | 584 | |
Troels Nilsson |
76:eef92651f52f | 585 | if (size != 0 && endpoint == EPCDC_OUT) |
Troels Nilsson |
76:eef92651f52f | 586 | { |
Troels Nilsson |
76:eef92651f52f | 587 | // terminal must be connected now since we received packets |
Troels Nilsson |
76:eef92651f52f | 588 | m_terminalConnected = true; |
Troels Nilsson |
76:eef92651f52f | 589 | } |
Troels Nilsson |
76:eef92651f52f | 590 | } |
Troels Nilsson |
76:eef92651f52f | 591 | return true; |
Troels Nilsson |
76:eef92651f52f | 592 | } |
Troels Nilsson |
76:eef92651f52f | 593 | |
Troels Nilsson |
77:a98f786d05d4 | 594 | bool USBWebUSBSerial::EPCDC_IN_callback() |
Troels Nilsson |
77:a98f786d05d4 | 595 | { |
Troels Nilsson |
77:a98f786d05d4 | 596 | CriticalSectionLock lock; |
Troels Nilsson |
77:a98f786d05d4 | 597 | if (!m_webUSBMode) |
Troels Nilsson |
77:a98f786d05d4 | 598 | { |
Troels Nilsson |
77:a98f786d05d4 | 599 | writeToActiveEndpoint(); |
Troels Nilsson |
77:a98f786d05d4 | 600 | } |
Troels Nilsson |
77:a98f786d05d4 | 601 | |
Troels Nilsson |
77:a98f786d05d4 | 602 | return true; |
Troels Nilsson |
77:a98f786d05d4 | 603 | } |
Troels Nilsson |
77:a98f786d05d4 | 604 | |
Troels Nilsson |
77:a98f786d05d4 | 605 | bool USBWebUSBSerial::EPWEBUSB_IN_callback() |
Troels Nilsson |
77:a98f786d05d4 | 606 | { |
Troels Nilsson |
77:a98f786d05d4 | 607 | CriticalSectionLock lock; |
Troels Nilsson |
77:a98f786d05d4 | 608 | if (m_webUSBMode) |
Troels Nilsson |
77:a98f786d05d4 | 609 | { |
Troels Nilsson |
77:a98f786d05d4 | 610 | writeToActiveEndpoint(); |
Troels Nilsson |
77:a98f786d05d4 | 611 | } |
Troels Nilsson |
77:a98f786d05d4 | 612 | |
Troels Nilsson |
77:a98f786d05d4 | 613 | return true; |
Troels Nilsson |
77:a98f786d05d4 | 614 | } |
Troels Nilsson |
77:a98f786d05d4 | 615 | |
Troels Nilsson |
76:eef92651f52f | 616 | uint8_t USBWebUSBSerial::available() |
Troels Nilsson |
76:eef92651f52f | 617 | { |
Troels Nilsson |
77:a98f786d05d4 | 618 | CriticalSectionLock lock; |
Troels Nilsson |
77:a98f786d05d4 | 619 | return m_inputBuffer.available(); |
Troels Nilsson |
76:eef92651f52f | 620 | } |
Troels Nilsson |
76:eef92651f52f | 621 | |
Troels Nilsson |
76:eef92651f52f | 622 | void USBWebUSBSerial::setManufacturerName(const std::string &manufacturerName) |
Troels Nilsson |
76:eef92651f52f | 623 | { |
Troels Nilsson |
76:eef92651f52f | 624 | m_manufacturerName = manufacturerName; |
Troels Nilsson |
78:ba3f68a86e6d | 625 | delete[] m_manufacturerStringDesc; |
Troels Nilsson |
76:eef92651f52f | 626 | m_manufacturerStringDesc = nullptr; |
Troels Nilsson |
76:eef92651f52f | 627 | createDynamicDescriptors(); |
Troels Nilsson |
76:eef92651f52f | 628 | } |
Troels Nilsson |
76:eef92651f52f | 629 | |
Troels Nilsson |
76:eef92651f52f | 630 | void USBWebUSBSerial::setProductName(const std::string &productName) |
Troels Nilsson |
76:eef92651f52f | 631 | { |
Troels Nilsson |
76:eef92651f52f | 632 | m_productName = productName; |
Troels Nilsson |
78:ba3f68a86e6d | 633 | delete[] m_productStringDesc; |
Troels Nilsson |
76:eef92651f52f | 634 | m_productStringDesc = nullptr; |
Troels Nilsson |
76:eef92651f52f | 635 | createDynamicDescriptors(); |
Troels Nilsson |
76:eef92651f52f | 636 | } |
Troels Nilsson |
76:eef92651f52f | 637 | |
Troels Nilsson |
76:eef92651f52f | 638 | void USBWebUSBSerial::setSerialNumber(const std::string &serialNumber) |
Troels Nilsson |
76:eef92651f52f | 639 | { |
Troels Nilsson |
76:eef92651f52f | 640 | m_serialNumber = serialNumber; |
Troels Nilsson |
78:ba3f68a86e6d | 641 | delete[] m_serialStringDesc; |
Troels Nilsson |
76:eef92651f52f | 642 | m_serialStringDesc = nullptr; |
Troels Nilsson |
76:eef92651f52f | 643 | createDynamicDescriptors(); |
Troels Nilsson |
76:eef92651f52f | 644 | } |
Troels Nilsson |
76:eef92651f52f | 645 | |
Troels Nilsson |
76:eef92651f52f | 646 | void USBWebUSBSerial::createDynamicDescriptors() |
Troels Nilsson |
76:eef92651f52f | 647 | { |
Troels Nilsson |
76:eef92651f52f | 648 | if (!m_manufacturerStringDesc) |
Troels Nilsson |
76:eef92651f52f | 649 | { |
Troels Nilsson |
76:eef92651f52f | 650 | m_manufacturerStringDesc = createStringDescriptor(m_manufacturerName); |
Troels Nilsson |
76:eef92651f52f | 651 | } |
Troels Nilsson |
76:eef92651f52f | 652 | if (!m_productStringDesc) |
Troels Nilsson |
76:eef92651f52f | 653 | { |
Troels Nilsson |
76:eef92651f52f | 654 | m_productStringDesc = createStringDescriptor(m_productName); |
Troels Nilsson |
76:eef92651f52f | 655 | } |
Troels Nilsson |
76:eef92651f52f | 656 | if (!m_serialStringDesc) |
Troels Nilsson |
76:eef92651f52f | 657 | { |
Troels Nilsson |
76:eef92651f52f | 658 | m_serialStringDesc = createStringDescriptor(m_serialNumber); |
Troels Nilsson |
76:eef92651f52f | 659 | } |
Troels Nilsson |
76:eef92651f52f | 660 | } |
Troels Nilsson |
76:eef92651f52f | 661 | |
Troels Nilsson |
76:eef92651f52f | 662 | uint8_t *USBWebUSBSerial::createStringDescriptor(const std::string &string) const |
Troels Nilsson |
76:eef92651f52f | 663 | { |
Troels Nilsson |
76:eef92651f52f | 664 | uint8_t stringSize = string.size()*2; |
Troels Nilsson |
76:eef92651f52f | 665 | uint8_t descriptorSize = 2 + stringSize; |
Troels Nilsson |
76:eef92651f52f | 666 | uint8_t *descriptor = new uint8_t[descriptorSize]; |
Troels Nilsson |
76:eef92651f52f | 667 | descriptor[0] = descriptorSize; // bLength |
Troels Nilsson |
76:eef92651f52f | 668 | descriptor[1] = STRING_DESCRIPTOR; // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 669 | for (int i = 0; i < stringSize/2; i++) |
Troels Nilsson |
76:eef92651f52f | 670 | { |
Troels Nilsson |
76:eef92651f52f | 671 | descriptor[(i*2)+2] = string[i]; |
Troels Nilsson |
76:eef92651f52f | 672 | descriptor[(i*2)+3] = 0; |
Troels Nilsson |
76:eef92651f52f | 673 | } |
Troels Nilsson |
76:eef92651f52f | 674 | return descriptor; |
Troels Nilsson |
77:a98f786d05d4 | 675 | } |
Troels Nilsson |
77:a98f786d05d4 | 676 | |
Troels Nilsson |
77:a98f786d05d4 | 677 | void USBWebUSBSerial::setWebUSBMode(bool webUSBMode) |
Troels Nilsson |
77:a98f786d05d4 | 678 | { |
Troels Nilsson |
77:a98f786d05d4 | 679 | CriticalSectionLock lock; |
Troels Nilsson |
77:a98f786d05d4 | 680 | if (webUSBMode != m_webUSBMode) |
Troels Nilsson |
77:a98f786d05d4 | 681 | { |
Troels Nilsson |
77:a98f786d05d4 | 682 | m_webUSBMode = webUSBMode; |
Troels Nilsson |
77:a98f786d05d4 | 683 | m_pendingWrite = false; |
Troels Nilsson |
77:a98f786d05d4 | 684 | |
Troels Nilsson |
77:a98f786d05d4 | 685 | // Clear buffers to clean out any left over data |
Troels Nilsson |
77:a98f786d05d4 | 686 | m_inputBuffer.flush(); |
Troels Nilsson |
77:a98f786d05d4 | 687 | m_outputBuffer.flush(); |
Troels Nilsson |
77:a98f786d05d4 | 688 | } |
Troels Nilsson |
77:a98f786d05d4 | 689 | } |
Troels Nilsson |
77:a98f786d05d4 | 690 | |
Troels Nilsson |
77:a98f786d05d4 | 691 | uint32_t USBWebUSBSerial::timeSinceWrite() const |
Troels Nilsson |
77:a98f786d05d4 | 692 | { |
Troels Nilsson |
77:a98f786d05d4 | 693 | uint32_t currentTime = osKernelGetTickCount(); |
Troels Nilsson |
77:a98f786d05d4 | 694 | if (currentTime < m_lastWriteTime) |
Troels Nilsson |
77:a98f786d05d4 | 695 | { |
Troels Nilsson |
77:a98f786d05d4 | 696 | // Tick count has wrapped around and started from 0 again |
Troels Nilsson |
77:a98f786d05d4 | 697 | return currentTime + (0xFFFFFFFF - m_lastWriteTime); |
Troels Nilsson |
77:a98f786d05d4 | 698 | } |
Troels Nilsson |
77:a98f786d05d4 | 699 | else |
Troels Nilsson |
77:a98f786d05d4 | 700 | { |
Troels Nilsson |
77:a98f786d05d4 | 701 | return currentTime - m_lastWriteTime; |
Troels Nilsson |
77:a98f786d05d4 | 702 | } |
Troels Nilsson |
76:eef92651f52f | 703 | } |