Fork of https://developer.mbed.org/users/bscott/code/STM32_USBDevice/
Fork of STM32_USBDevice by
USBSerial/USBWebUSBSerial.cpp@77:a98f786d05d4, 2018-07-24 (annotated)
- Committer:
- Troels Nilsson
- Date:
- Tue Jul 24 13:08:29 2018 +0200
- Branch:
- feature_WebUSB
- Revision:
- 77:a98f786d05d4
- Parent:
- 76:eef92651f52f
- Child:
- 78:ba3f68a86e6d
Changed USBWebUSBSerial to use non-blocking writes
USBWebUSBSerial now uses an internal buffer to do non-blocking, async writes
Expanded CircBuffer to be able to queue/dequeue a block of data (to avoid looping a lot)
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 |
76:eef92651f52f | 116 | void USBWebUSBSerial::USBCallback_busReset() |
Troels Nilsson |
76:eef92651f52f | 117 | { |
Troels Nilsson |
76:eef92651f52f | 118 | m_terminalConnected = false; |
Troels Nilsson |
77:a98f786d05d4 | 119 | m_pendingWrite = false; |
Troels Nilsson |
77:a98f786d05d4 | 120 | setWebUSBMode(false); |
Troels Nilsson |
76:eef92651f52f | 121 | } |
Troels Nilsson |
76:eef92651f52f | 122 | |
Troels Nilsson |
76:eef92651f52f | 123 | bool USBWebUSBSerial::USBCallback_request() |
Troels Nilsson |
76:eef92651f52f | 124 | { |
Troels Nilsson |
76:eef92651f52f | 125 | /* Called in ISR context */ |
Troels Nilsson |
76:eef92651f52f | 126 | |
Troels Nilsson |
76:eef92651f52f | 127 | bool success = false; |
Troels Nilsson |
76:eef92651f52f | 128 | CONTROL_TRANSFER * transfer = getTransferPtr(); |
Troels Nilsson |
76:eef92651f52f | 129 | |
Troels Nilsson |
76:eef92651f52f | 130 | /* Process class-specific requests */ |
Troels Nilsson |
76:eef92651f52f | 131 | if (transfer->setup.bmRequestType.Type == CLASS_TYPE) |
Troels Nilsson |
76:eef92651f52f | 132 | { |
Troels Nilsson |
76:eef92651f52f | 133 | switch (transfer->setup.bRequest) |
Troels Nilsson |
76:eef92651f52f | 134 | { |
Troels Nilsson |
76:eef92651f52f | 135 | case CDC_GET_LINE_CODING: |
Troels Nilsson |
76:eef92651f52f | 136 | transfer->remaining = 7; |
Troels Nilsson |
76:eef92651f52f | 137 | transfer->ptr = cdc_line_coding; |
Troels Nilsson |
76:eef92651f52f | 138 | transfer->direction = DEVICE_TO_HOST; |
Troels Nilsson |
76:eef92651f52f | 139 | success = true; |
Troels Nilsson |
76:eef92651f52f | 140 | break; |
Troels Nilsson |
76:eef92651f52f | 141 | case CDC_SET_LINE_CODING: |
Troels Nilsson |
76:eef92651f52f | 142 | transfer->remaining = 7; |
Troels Nilsson |
76:eef92651f52f | 143 | transfer->notify = true; |
Troels Nilsson |
76:eef92651f52f | 144 | success = true; |
Troels Nilsson |
76:eef92651f52f | 145 | break; |
Troels Nilsson |
76:eef92651f52f | 146 | case CDC_SET_CONTROL_LINE_STATE: |
Troels Nilsson |
76:eef92651f52f | 147 | if (transfer->setup.wValue & CLS_DTR) { |
Troels Nilsson |
76:eef92651f52f | 148 | m_terminalConnected = true; |
Troels Nilsson |
76:eef92651f52f | 149 | } else { |
Troels Nilsson |
76:eef92651f52f | 150 | m_terminalConnected = false; |
Troels Nilsson |
77:a98f786d05d4 | 151 | if (!m_webUSBMode) |
Troels Nilsson |
77:a98f786d05d4 | 152 | { |
Troels Nilsson |
77:a98f786d05d4 | 153 | m_pendingWrite = false; |
Troels Nilsson |
77:a98f786d05d4 | 154 | } |
Troels Nilsson |
76:eef92651f52f | 155 | } |
Troels Nilsson |
76:eef92651f52f | 156 | success = true; |
Troels Nilsson |
76:eef92651f52f | 157 | break; |
Troels Nilsson |
76:eef92651f52f | 158 | default: |
Troels Nilsson |
76:eef92651f52f | 159 | break; |
Troels Nilsson |
76:eef92651f52f | 160 | } |
Troels Nilsson |
76:eef92651f52f | 161 | } |
Troels Nilsson |
76:eef92651f52f | 162 | 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 | 163 | { |
Troels Nilsson |
76:eef92651f52f | 164 | // Request for the MS OS 2.0 descriptor |
Troels Nilsson |
76:eef92651f52f | 165 | transfer->remaining = MS_OS_20_DESCRIPTOR_LENGTH; |
Troels Nilsson |
76:eef92651f52f | 166 | transfer->ptr = s_MSOS2Descriptor; |
Troels Nilsson |
76:eef92651f52f | 167 | transfer->direction = DEVICE_TO_HOST; |
Troels Nilsson |
76:eef92651f52f | 168 | success = true; |
Troels Nilsson |
76:eef92651f52f | 169 | } |
Troels Nilsson |
76:eef92651f52f | 170 | else if (transfer->setup.bmRequestType.Type == VENDOR_TYPE && transfer->setup.bRequest == SET_WEBUSB_ACTIVE_VENDOR_CODE) |
Troels Nilsson |
76:eef92651f52f | 171 | { |
Troels Nilsson |
76:eef92651f52f | 172 | if (transfer->setup.wValue == 0) |
Troels Nilsson |
76:eef92651f52f | 173 | { |
Troels Nilsson |
76:eef92651f52f | 174 | // Disable WebUSB mode |
Troels Nilsson |
77:a98f786d05d4 | 175 | setWebUSBMode(false); |
Troels Nilsson |
76:eef92651f52f | 176 | } |
Troels Nilsson |
76:eef92651f52f | 177 | else |
Troels Nilsson |
76:eef92651f52f | 178 | { |
Troels Nilsson |
76:eef92651f52f | 179 | // Enable WebUSB mode |
Troels Nilsson |
77:a98f786d05d4 | 180 | setWebUSBMode(true); |
Troels Nilsson |
76:eef92651f52f | 181 | } |
Troels Nilsson |
76:eef92651f52f | 182 | success = true; |
Troels Nilsson |
76:eef92651f52f | 183 | } |
Troels Nilsson |
76:eef92651f52f | 184 | |
Troels Nilsson |
76:eef92651f52f | 185 | return success; |
Troels Nilsson |
76:eef92651f52f | 186 | } |
Troels Nilsson |
76:eef92651f52f | 187 | |
Troels Nilsson |
76:eef92651f52f | 188 | void USBWebUSBSerial::USBCallback_requestCompleted(uint8_t *buf, uint32_t length) |
Troels Nilsson |
76:eef92651f52f | 189 | { |
Troels Nilsson |
76:eef92651f52f | 190 | // Request of setting line coding has 7 bytes |
Troels Nilsson |
76:eef92651f52f | 191 | if (length != 7) |
Troels Nilsson |
76:eef92651f52f | 192 | { |
Troels Nilsson |
76:eef92651f52f | 193 | return; |
Troels Nilsson |
76:eef92651f52f | 194 | } |
Troels Nilsson |
76:eef92651f52f | 195 | |
Troels Nilsson |
76:eef92651f52f | 196 | CONTROL_TRANSFER * transfer = getTransferPtr(); |
Troels Nilsson |
76:eef92651f52f | 197 | |
Troels Nilsson |
76:eef92651f52f | 198 | /* Process class-specific requests */ |
Troels Nilsson |
76:eef92651f52f | 199 | if (transfer->setup.bmRequestType.Type == CLASS_TYPE) |
Troels Nilsson |
76:eef92651f52f | 200 | { |
Troels Nilsson |
76:eef92651f52f | 201 | if (transfer->setup.bRequest == CDC_SET_LINE_CODING) |
Troels Nilsson |
76:eef92651f52f | 202 | { |
Troels Nilsson |
76:eef92651f52f | 203 | if (memcmp(cdc_line_coding, buf, 7)) |
Troels Nilsson |
76:eef92651f52f | 204 | { |
Troels Nilsson |
76:eef92651f52f | 205 | memcpy(cdc_line_coding, buf, 7); |
Troels Nilsson |
76:eef92651f52f | 206 | |
Troels Nilsson |
76:eef92651f52f | 207 | int baud = buf[0] + (buf[1] << 8) |
Troels Nilsson |
76:eef92651f52f | 208 | + (buf[2] << 16) + (buf[3] << 24); |
Troels Nilsson |
76:eef92651f52f | 209 | int stop = buf[4]; |
Troels Nilsson |
76:eef92651f52f | 210 | int bits = buf[6]; |
Troels Nilsson |
76:eef92651f52f | 211 | int parity = buf[5]; |
Troels Nilsson |
76:eef92651f52f | 212 | |
Troels Nilsson |
76:eef92651f52f | 213 | lineCodingChanged(baud, bits, parity, stop); |
Troels Nilsson |
76:eef92651f52f | 214 | } |
Troels Nilsson |
76:eef92651f52f | 215 | } |
Troels Nilsson |
76:eef92651f52f | 216 | } |
Troels Nilsson |
76:eef92651f52f | 217 | } |
Troels Nilsson |
76:eef92651f52f | 218 | |
Troels Nilsson |
76:eef92651f52f | 219 | // Called in ISR context |
Troels Nilsson |
76:eef92651f52f | 220 | // Set configuration. Return false if the |
Troels Nilsson |
76:eef92651f52f | 221 | // configuration is not supported. |
Troels Nilsson |
76:eef92651f52f | 222 | bool USBWebUSBSerial::USBCallback_setConfiguration(uint8_t configuration) |
Troels Nilsson |
76:eef92651f52f | 223 | { |
Troels Nilsson |
76:eef92651f52f | 224 | if (configuration != DEFAULT_CONFIGURATION) |
Troels Nilsson |
76:eef92651f52f | 225 | { |
Troels Nilsson |
76:eef92651f52f | 226 | return false; |
Troels Nilsson |
76:eef92651f52f | 227 | } |
Troels Nilsson |
76:eef92651f52f | 228 | |
Troels Nilsson |
76:eef92651f52f | 229 | if (configured()) |
Troels Nilsson |
76:eef92651f52f | 230 | { |
Troels Nilsson |
76:eef92651f52f | 231 | // Already configured, nothing to do |
Troels Nilsson |
76:eef92651f52f | 232 | return true; |
Troels Nilsson |
76:eef92651f52f | 233 | } |
Troels Nilsson |
76:eef92651f52f | 234 | |
Troels Nilsson |
76:eef92651f52f | 235 | // Configure endpoints > 0 |
Troels Nilsson |
76:eef92651f52f | 236 | addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT); |
Troels Nilsson |
76:eef92651f52f | 237 | addEndpoint(EPCDC_IN, MAX_PACKET_SIZE_EPBULK); |
Troels Nilsson |
76:eef92651f52f | 238 | addEndpoint(EPCDC_OUT, MAX_PACKET_SIZE_EPBULK); |
Troels Nilsson |
76:eef92651f52f | 239 | addEndpoint(EPWEBUSB_IN, MAX_PACKET_SIZE_EPBULK); |
Troels Nilsson |
76:eef92651f52f | 240 | addEndpoint(EPWEBUSB_OUT, MAX_PACKET_SIZE_EPBULK); |
Troels Nilsson |
76:eef92651f52f | 241 | |
Troels Nilsson |
76:eef92651f52f | 242 | // We activate the endpoints to be able to receive data |
Troels Nilsson |
76:eef92651f52f | 243 | readStart(EPCDC_OUT, MAX_PACKET_SIZE_EPBULK); |
Troels Nilsson |
76:eef92651f52f | 244 | readStart(EPWEBUSB_OUT, MAX_PACKET_SIZE_EPBULK); |
Troels Nilsson |
76:eef92651f52f | 245 | return true; |
Troels Nilsson |
76:eef92651f52f | 246 | } |
Troels Nilsson |
76:eef92651f52f | 247 | |
Troels Nilsson |
77:a98f786d05d4 | 248 | void USBWebUSBSerial::writeToActiveEndpoint() |
Troels Nilsson |
76:eef92651f52f | 249 | { |
Troels Nilsson |
77:a98f786d05d4 | 250 | CriticalSectionLock lock; |
Troels Nilsson |
77:a98f786d05d4 | 251 | if(!configured() || m_outputBuffer.isEmpty()) |
Troels Nilsson |
76:eef92651f52f | 252 | { |
Troels Nilsson |
77:a98f786d05d4 | 253 | m_pendingWrite = false; |
Troels Nilsson |
77:a98f786d05d4 | 254 | return; |
Troels Nilsson |
77:a98f786d05d4 | 255 | } |
Troels Nilsson |
76:eef92651f52f | 256 | |
Troels Nilsson |
77:a98f786d05d4 | 257 | uint8_t buffer[MAX_PACKET_SIZE_EPBULK]; |
Troels Nilsson |
77:a98f786d05d4 | 258 | uint16_t size = m_outputBuffer.dequeue(buffer, MAX_PACKET_SIZE_EPBULK); |
Troels Nilsson |
76:eef92651f52f | 259 | |
Troels Nilsson |
77:a98f786d05d4 | 260 | EP_STATUS result = endpointWrite(activeInEndpoint(), buffer, size); |
Troels Nilsson |
76:eef92651f52f | 261 | |
Troels Nilsson |
77:a98f786d05d4 | 262 | if (result != EP_PENDING) |
Troels Nilsson |
77:a98f786d05d4 | 263 | { |
Troels Nilsson |
77:a98f786d05d4 | 264 | return; |
Troels Nilsson |
77:a98f786d05d4 | 265 | } |
Troels Nilsson |
76:eef92651f52f | 266 | |
Troels Nilsson |
77:a98f786d05d4 | 267 | m_lastWriteTime = osKernelGetTickCount(); |
Troels Nilsson |
77:a98f786d05d4 | 268 | m_pendingWrite = true; |
Troels Nilsson |
76:eef92651f52f | 269 | } |
Troels Nilsson |
76:eef92651f52f | 270 | |
Troels Nilsson |
76:eef92651f52f | 271 | bool USBWebUSBSerial::readActiveEP() |
Troels Nilsson |
76:eef92651f52f | 272 | { |
Troels Nilsson |
77:a98f786d05d4 | 273 | CriticalSectionLock lock; |
Troels Nilsson |
76:eef92651f52f | 274 | uint8_t buffer[MAX_PACKET_SIZE_EPBULK]; |
Troels Nilsson |
76:eef92651f52f | 275 | uint32_t size = 0; |
Troels Nilsson |
76:eef92651f52f | 276 | if (!USBDevice::readEP_NB(activeOutEndpoint(), buffer, &size, MAX_PACKET_SIZE_EPBULK)) |
Troels Nilsson |
76:eef92651f52f | 277 | { |
Troels Nilsson |
76:eef92651f52f | 278 | return false; |
Troels Nilsson |
76:eef92651f52f | 279 | } |
Troels Nilsson |
76:eef92651f52f | 280 | if (!readStart(activeOutEndpoint(), MAX_PACKET_SIZE_EPBULK)) |
Troels Nilsson |
76:eef92651f52f | 281 | { |
Troels Nilsson |
76:eef92651f52f | 282 | return false; |
Troels Nilsson |
76:eef92651f52f | 283 | } |
Troels Nilsson |
76:eef92651f52f | 284 | |
Troels Nilsson |
77:a98f786d05d4 | 285 | m_inputBuffer.queue(buffer, size); |
Troels Nilsson |
76:eef92651f52f | 286 | |
Troels Nilsson |
76:eef92651f52f | 287 | if (size != 0 && activeOutEndpoint() == EPCDC_OUT) |
Troels Nilsson |
76:eef92651f52f | 288 | { |
Troels Nilsson |
76:eef92651f52f | 289 | // terminal must be connected now since we received packets |
Troels Nilsson |
76:eef92651f52f | 290 | m_terminalConnected = true; |
Troels Nilsson |
76:eef92651f52f | 291 | } |
Troels Nilsson |
76:eef92651f52f | 292 | |
Troels Nilsson |
76:eef92651f52f | 293 | // call a potential handler |
Troels Nilsson |
76:eef92651f52f | 294 | if (m_rx) |
Troels Nilsson |
76:eef92651f52f | 295 | { |
Troels Nilsson |
76:eef92651f52f | 296 | m_rx.call(); |
Troels Nilsson |
76:eef92651f52f | 297 | } |
Troels Nilsson |
76:eef92651f52f | 298 | |
Troels Nilsson |
76:eef92651f52f | 299 | return true; |
Troels Nilsson |
76:eef92651f52f | 300 | } |
Troels Nilsson |
76:eef92651f52f | 301 | |
Troels Nilsson |
76:eef92651f52f | 302 | uint8_t * USBWebUSBSerial::deviceDesc() |
Troels Nilsson |
76:eef92651f52f | 303 | { |
Troels Nilsson |
76:eef92651f52f | 304 | static uint8_t deviceDescriptor[] = { |
Troels Nilsson |
76:eef92651f52f | 305 | DEVICE_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 306 | DEVICE_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 307 | 0x10, 0x02, // bcdUSB = 2.10 |
Troels Nilsson |
76:eef92651f52f | 308 | 0, // bDeviceClass: composite (unspecified on device level) |
Troels Nilsson |
76:eef92651f52f | 309 | 0, // bDeviceSubClass |
Troels Nilsson |
76:eef92651f52f | 310 | 0, // bDeviceProtocol |
Troels Nilsson |
76:eef92651f52f | 311 | MAX_PACKET_SIZE_EP0, // bMaxPacketSize0 |
Troels Nilsson |
76:eef92651f52f | 312 | (uint8_t)(LSB(VENDOR_ID)), (uint8_t)(MSB(VENDOR_ID)), // idVendor |
Troels Nilsson |
76:eef92651f52f | 313 | (uint8_t)(LSB(PRODUCT_ID)), (uint8_t)(MSB(PRODUCT_ID)),// idProduct |
Troels Nilsson |
76:eef92651f52f | 314 | 0x00, 0x01, // bcdDevice |
Troels Nilsson |
76:eef92651f52f | 315 | STRING_OFFSET_IMANUFACTURER, // iManufacturer |
Troels Nilsson |
76:eef92651f52f | 316 | STRING_OFFSET_IPRODUCT, // iProduct |
Troels Nilsson |
76:eef92651f52f | 317 | STRING_OFFSET_ISERIAL, // iSerialNumber |
Troels Nilsson |
76:eef92651f52f | 318 | 1 // bNumConfigurations |
Troels Nilsson |
76:eef92651f52f | 319 | }; |
Troels Nilsson |
76:eef92651f52f | 320 | return deviceDescriptor; |
Troels Nilsson |
76:eef92651f52f | 321 | } |
Troels Nilsson |
76:eef92651f52f | 322 | |
Troels Nilsson |
76:eef92651f52f | 323 | uint8_t * USBWebUSBSerial::stringImanufacturerDesc() |
Troels Nilsson |
76:eef92651f52f | 324 | { |
Troels Nilsson |
76:eef92651f52f | 325 | return m_manufacturerStringDesc; |
Troels Nilsson |
76:eef92651f52f | 326 | } |
Troels Nilsson |
76:eef92651f52f | 327 | |
Troels Nilsson |
76:eef92651f52f | 328 | uint8_t * USBWebUSBSerial::stringIproductDesc() |
Troels Nilsson |
76:eef92651f52f | 329 | { |
Troels Nilsson |
76:eef92651f52f | 330 | return m_productStringDesc; |
Troels Nilsson |
76:eef92651f52f | 331 | } |
Troels Nilsson |
76:eef92651f52f | 332 | |
Troels Nilsson |
76:eef92651f52f | 333 | uint8_t * USBWebUSBSerial::stringIserialDesc() |
Troels Nilsson |
76:eef92651f52f | 334 | { |
Troels Nilsson |
76:eef92651f52f | 335 | return m_serialStringDesc; |
Troels Nilsson |
76:eef92651f52f | 336 | } |
Troels Nilsson |
76:eef92651f52f | 337 | |
Troels Nilsson |
76:eef92651f52f | 338 | #define CONFIG1_DESC_SIZE (CONFIGURATION_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 339 | INTERFACE_ASSOCIATION_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 340 | INTERFACE_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 341 | 5+5+4+5 + \ |
Troels Nilsson |
76:eef92651f52f | 342 | ENDPOINT_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 343 | INTERFACE_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 344 | ENDPOINT_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 345 | ENDPOINT_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 346 | INTERFACE_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 347 | ENDPOINT_DESCRIPTOR_LENGTH + \ |
Troels Nilsson |
76:eef92651f52f | 348 | ENDPOINT_DESCRIPTOR_LENGTH) |
Troels Nilsson |
76:eef92651f52f | 349 | |
Troels Nilsson |
76:eef92651f52f | 350 | uint8_t * USBWebUSBSerial::configurationDesc() |
Troels Nilsson |
76:eef92651f52f | 351 | { |
Troels Nilsson |
76:eef92651f52f | 352 | static uint8_t configDescriptor[] = { |
Troels Nilsson |
76:eef92651f52f | 353 | // configuration descriptor |
Troels Nilsson |
76:eef92651f52f | 354 | CONFIGURATION_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 355 | CONFIGURATION_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 356 | LSB(CONFIG1_DESC_SIZE), // wTotalLength |
Troels Nilsson |
76:eef92651f52f | 357 | MSB(CONFIG1_DESC_SIZE), |
Troels Nilsson |
76:eef92651f52f | 358 | 3, // bNumInterfaces |
Troels Nilsson |
76:eef92651f52f | 359 | 1, // bConfigurationValue |
Troels Nilsson |
76:eef92651f52f | 360 | 0, // iConfiguration |
Troels Nilsson |
76:eef92651f52f | 361 | 0x80, // bmAttributes |
Troels Nilsson |
76:eef92651f52f | 362 | 50, // bMaxPower |
Troels Nilsson |
76:eef92651f52f | 363 | |
Troels Nilsson |
76:eef92651f52f | 364 | // IAD to associate the two CDC interfaces |
Troels Nilsson |
76:eef92651f52f | 365 | INTERFACE_ASSOCIATION_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 366 | INTERFACE_ASSOCIATION_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 367 | 0x00, // bFirstInterface |
Troels Nilsson |
76:eef92651f52f | 368 | 0x02, // bInterfaceCount |
Troels Nilsson |
76:eef92651f52f | 369 | USB_CDC_CLASS, // bFunctionClass |
Troels Nilsson |
76:eef92651f52f | 370 | USB_ACM_SUBCLASS, // bFunctionSubClass |
Troels Nilsson |
76:eef92651f52f | 371 | 0, // bFunctionProtocol |
Troels Nilsson |
76:eef92651f52f | 372 | 0, // iFunction |
Troels Nilsson |
76:eef92651f52f | 373 | |
Troels Nilsson |
76:eef92651f52f | 374 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 |
Troels Nilsson |
76:eef92651f52f | 375 | INTERFACE_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 376 | INTERFACE_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 377 | 0, // bInterfaceNumber |
Troels Nilsson |
76:eef92651f52f | 378 | 0, // bAlternateSetting |
Troels Nilsson |
76:eef92651f52f | 379 | 1, // bNumEndpoints |
Troels Nilsson |
76:eef92651f52f | 380 | USB_CDC_CLASS, // bInterfaceClass |
Troels Nilsson |
76:eef92651f52f | 381 | USB_ACM_SUBCLASS, // bInterfaceSubClass |
Troels Nilsson |
76:eef92651f52f | 382 | 0x01, // bInterfaceProtocol |
Troels Nilsson |
76:eef92651f52f | 383 | 0, // iInterface |
Troels Nilsson |
76:eef92651f52f | 384 | |
Troels Nilsson |
76:eef92651f52f | 385 | // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 |
Troels Nilsson |
76:eef92651f52f | 386 | 5, // bFunctionLength |
Troels Nilsson |
76:eef92651f52f | 387 | USB_CS_INTERFACE, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 388 | USB_HEADER_FUNCTION_DESCRIPTOR_TYPE, // bDescriptorSubtype |
Troels Nilsson |
76:eef92651f52f | 389 | 0x10, 0x01, // bcdCDC |
Troels Nilsson |
76:eef92651f52f | 390 | |
Troels Nilsson |
76:eef92651f52f | 391 | // Call Management Functional Descriptor, CDC PSTN Spec 5.3.1, Table 3 |
Troels Nilsson |
76:eef92651f52f | 392 | 5, // bFunctionLength |
Troels Nilsson |
76:eef92651f52f | 393 | USB_CS_INTERFACE, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 394 | USB_CALL_MANAGEMENT_FUNCTION_DESCRIPTOR_TYPE, // bDescriptorSubtype |
Troels Nilsson |
76:eef92651f52f | 395 | 0x03, // bmCapabilities |
Troels Nilsson |
76:eef92651f52f | 396 | 1, // bDataInterface |
Troels Nilsson |
76:eef92651f52f | 397 | |
Troels Nilsson |
76:eef92651f52f | 398 | // Abstract Control Management Functional Descriptor, CDC PSTN Spec 5.3.2, Table 4 |
Troels Nilsson |
76:eef92651f52f | 399 | 4, // bFunctionLength |
Troels Nilsson |
76:eef92651f52f | 400 | USB_CS_INTERFACE, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 401 | USB_ABSTRACT_CONTROL_MANAGEMENT_FUNCTION_DESCRIPTOR_TYPE, // bDescriptorSubtype |
Troels Nilsson |
76:eef92651f52f | 402 | 0x06, // bmCapabilities |
Troels Nilsson |
76:eef92651f52f | 403 | |
Troels Nilsson |
76:eef92651f52f | 404 | // Union Functional Descriptor, CDC Spec 5.2.3.2, Table 16 |
Troels Nilsson |
76:eef92651f52f | 405 | 5, // bFunctionLength |
Troels Nilsson |
76:eef92651f52f | 406 | USB_CS_INTERFACE, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 407 | USB_UNION_INTERFACE_FUNCTION_DESCRIPTOR_TYPE, // bDescriptorSubtype |
Troels Nilsson |
76:eef92651f52f | 408 | 0, // bMasterInterface |
Troels Nilsson |
76:eef92651f52f | 409 | 1, // bSlaveInterface0 |
Troels Nilsson |
76:eef92651f52f | 410 | |
Troels Nilsson |
76:eef92651f52f | 411 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 |
Troels Nilsson |
76:eef92651f52f | 412 | ENDPOINT_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 413 | ENDPOINT_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 414 | PHY_TO_DESC(EPINT_IN), // bEndpointAddress |
Troels Nilsson |
76:eef92651f52f | 415 | E_INTERRUPT, // bmAttributes (0x03=intr) |
Troels Nilsson |
76:eef92651f52f | 416 | LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) |
Troels Nilsson |
76:eef92651f52f | 417 | MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) |
Troels Nilsson |
76:eef92651f52f | 418 | 16, // bInterval |
Troels Nilsson |
76:eef92651f52f | 419 | |
Troels Nilsson |
76:eef92651f52f | 420 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 |
Troels Nilsson |
76:eef92651f52f | 421 | INTERFACE_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 422 | INTERFACE_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 423 | 1, // bInterfaceNumber |
Troels Nilsson |
76:eef92651f52f | 424 | 0, // bAlternateSetting |
Troels Nilsson |
76:eef92651f52f | 425 | 2, // bNumEndpoints |
Troels Nilsson |
76:eef92651f52f | 426 | USB_CDC_DATA_CLASS, // bInterfaceClass |
Troels Nilsson |
76:eef92651f52f | 427 | 0x00, // bInterfaceSubClass |
Troels Nilsson |
76:eef92651f52f | 428 | 0x00, // bInterfaceProtocol |
Troels Nilsson |
76:eef92651f52f | 429 | 0, // iInterface |
Troels Nilsson |
76:eef92651f52f | 430 | |
Troels Nilsson |
76:eef92651f52f | 431 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 |
Troels Nilsson |
76:eef92651f52f | 432 | ENDPOINT_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 433 | ENDPOINT_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 434 | PHY_TO_DESC(EPCDC_IN), // bEndpointAddress |
Troels Nilsson |
76:eef92651f52f | 435 | E_BULK, // bmAttributes (0x02=bulk) |
Troels Nilsson |
76:eef92651f52f | 436 | LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) |
Troels Nilsson |
76:eef92651f52f | 437 | MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) |
Troels Nilsson |
76:eef92651f52f | 438 | 0, // bInterval |
Troels Nilsson |
76:eef92651f52f | 439 | |
Troels Nilsson |
76:eef92651f52f | 440 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 |
Troels Nilsson |
76:eef92651f52f | 441 | ENDPOINT_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 442 | ENDPOINT_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 443 | PHY_TO_DESC(EPCDC_OUT), // bEndpointAddress |
Troels Nilsson |
76:eef92651f52f | 444 | E_BULK, // bmAttributes (0x02=bulk) |
Troels Nilsson |
76:eef92651f52f | 445 | LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) |
Troels Nilsson |
76:eef92651f52f | 446 | MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) |
Troels Nilsson |
76:eef92651f52f | 447 | 0, // bInterval |
Troels Nilsson |
76:eef92651f52f | 448 | |
Troels Nilsson |
76:eef92651f52f | 449 | // WebUSB interface |
Troels Nilsson |
76:eef92651f52f | 450 | INTERFACE_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 451 | INTERFACE_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 452 | 2, // bInterfaceNumber |
Troels Nilsson |
76:eef92651f52f | 453 | 0, // bAlternateSetting |
Troels Nilsson |
76:eef92651f52f | 454 | 2, // bNumEndpoints |
Troels Nilsson |
76:eef92651f52f | 455 | USB_CUSTOM_CLASS, // bInterfaceClass |
Troels Nilsson |
76:eef92651f52f | 456 | 0x00, // bInterfaceSubClass |
Troels Nilsson |
76:eef92651f52f | 457 | 0x00, // bInterfaceProtocol |
Troels Nilsson |
76:eef92651f52f | 458 | 0, // iInterface |
Troels Nilsson |
76:eef92651f52f | 459 | |
Troels Nilsson |
76:eef92651f52f | 460 | // WebUSB IN endpoint |
Troels Nilsson |
76:eef92651f52f | 461 | ENDPOINT_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 462 | ENDPOINT_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 463 | PHY_TO_DESC(EPWEBUSB_IN), // bEndpointAddress |
Troels Nilsson |
76:eef92651f52f | 464 | E_BULK, // bmAttributes (0x02=bulk) |
Troels Nilsson |
76:eef92651f52f | 465 | LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) |
Troels Nilsson |
76:eef92651f52f | 466 | MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) |
Troels Nilsson |
76:eef92651f52f | 467 | 0, // bInterval |
Troels Nilsson |
76:eef92651f52f | 468 | |
Troels Nilsson |
76:eef92651f52f | 469 | // WebUSB OUT endpoint |
Troels Nilsson |
76:eef92651f52f | 470 | ENDPOINT_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 471 | ENDPOINT_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 472 | PHY_TO_DESC(EPWEBUSB_OUT), // bEndpointAddress |
Troels Nilsson |
76:eef92651f52f | 473 | E_BULK, // bmAttributes (0x02=bulk) |
Troels Nilsson |
76:eef92651f52f | 474 | LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) |
Troels Nilsson |
76:eef92651f52f | 475 | MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) |
Troels Nilsson |
76:eef92651f52f | 476 | 0 // bInterval |
Troels Nilsson |
76:eef92651f52f | 477 | }; |
Troels Nilsson |
76:eef92651f52f | 478 | return configDescriptor; |
Troels Nilsson |
76:eef92651f52f | 479 | } |
Troels Nilsson |
76:eef92651f52f | 480 | |
Troels Nilsson |
76:eef92651f52f | 481 | #define BOS_MSOS2_PLATFORM_DESCRIPTOR_LENGTH 28 |
Troels Nilsson |
76:eef92651f52f | 482 | #define BOS_TOTAL_LENGTH (BOS_DESCRIPTOR_LENGTH + BOS_MSOS2_PLATFORM_DESCRIPTOR_LENGTH) |
Troels Nilsson |
76:eef92651f52f | 483 | |
Troels Nilsson |
76:eef92651f52f | 484 | uint8_t * USBWebUSBSerial::bosDesc() |
Troels Nilsson |
76:eef92651f52f | 485 | { |
Troels Nilsson |
76:eef92651f52f | 486 | static uint8_t bosDescriptor[] = { |
Troels Nilsson |
76:eef92651f52f | 487 | BOS_DESCRIPTOR_LENGTH, // bLength |
Troels Nilsson |
76:eef92651f52f | 488 | BOS_DESCRIPTOR, // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 489 | LSB(BOS_TOTAL_LENGTH), // wTotalLength (LSB) |
Troels Nilsson |
76:eef92651f52f | 490 | MSB(BOS_TOTAL_LENGTH), // wTotalLength (MSB) |
Troels Nilsson |
76:eef92651f52f | 491 | 0x01, // bNumDeviceCaps |
Troels Nilsson |
76:eef92651f52f | 492 | |
Troels Nilsson |
76:eef92651f52f | 493 | // MS OS 2.0 descriptors information |
Troels Nilsson |
76:eef92651f52f | 494 | BOS_MSOS2_PLATFORM_DESCRIPTOR_LENGTH, |
Troels Nilsson |
76:eef92651f52f | 495 | DEVICE_CAPABILITY_DESCRIPTOR, |
Troels Nilsson |
76:eef92651f52f | 496 | PLATFORM_DEVICE_CAPABILITY_TYPE, |
Troels Nilsson |
76:eef92651f52f | 497 | 0x00, // bReserved |
Troels Nilsson |
76:eef92651f52f | 498 | 0xDF, 0x60, 0xDD, 0xD8, // PlatformCapabilityUUID ({D8DD60DF-4589-4CC7-9CD2-659D9E648A9F}) |
Troels Nilsson |
76:eef92651f52f | 499 | 0x89, 0x45, |
Troels Nilsson |
76:eef92651f52f | 500 | 0xC7, 0x4C, |
Troels Nilsson |
76:eef92651f52f | 501 | 0x9C, 0xD2, |
Troels Nilsson |
76:eef92651f52f | 502 | 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F, |
Troels Nilsson |
76:eef92651f52f | 503 | |
Troels Nilsson |
76:eef92651f52f | 504 | 0x00, 0x00, 0x03, 0x06, // Windows version (8.1 = 0x06030000) |
Troels Nilsson |
76:eef92651f52f | 505 | LSB(MS_OS_20_DESCRIPTOR_LENGTH), // wMSOSDecriptorSetTotalLength (LSB) |
Troels Nilsson |
76:eef92651f52f | 506 | MSB(MS_OS_20_DESCRIPTOR_LENGTH), // wMSOSDecriptorSetTotalLength (MSB) |
Troels Nilsson |
76:eef92651f52f | 507 | WINUSB_VENDOR_CODE, // bMS_VendorCode |
Troels Nilsson |
76:eef92651f52f | 508 | 0x00 // bAltEnum |
Troels Nilsson |
76:eef92651f52f | 509 | }; |
Troels Nilsson |
76:eef92651f52f | 510 | return bosDescriptor; |
Troels Nilsson |
76:eef92651f52f | 511 | } |
Troels Nilsson |
76:eef92651f52f | 512 | |
Troels Nilsson |
76:eef92651f52f | 513 | |
Troels Nilsson |
76:eef92651f52f | 514 | int USBWebUSBSerial::_putc(int c) |
Troels Nilsson |
76:eef92651f52f | 515 | { |
Troels Nilsson |
77:a98f786d05d4 | 516 | if (!writeBuffered((uint8_t *)&c, 1)) |
Troels Nilsson |
76:eef92651f52f | 517 | { |
Troels Nilsson |
76:eef92651f52f | 518 | return 0; |
Troels Nilsson |
76:eef92651f52f | 519 | } |
Troels Nilsson |
76:eef92651f52f | 520 | return 1; |
Troels Nilsson |
76:eef92651f52f | 521 | } |
Troels Nilsson |
76:eef92651f52f | 522 | |
Troels Nilsson |
76:eef92651f52f | 523 | int USBWebUSBSerial::_getc() |
Troels Nilsson |
76:eef92651f52f | 524 | { |
Troels Nilsson |
76:eef92651f52f | 525 | uint8_t c = 0; |
Troels Nilsson |
77:a98f786d05d4 | 526 | while (!available()); |
Troels Nilsson |
77:a98f786d05d4 | 527 | CriticalSectionLock lock; |
Troels Nilsson |
77:a98f786d05d4 | 528 | m_inputBuffer.dequeue(&c); |
Troels Nilsson |
76:eef92651f52f | 529 | return c; |
Troels Nilsson |
76:eef92651f52f | 530 | } |
Troels Nilsson |
76:eef92651f52f | 531 | |
Troels Nilsson |
77:a98f786d05d4 | 532 | bool USBWebUSBSerial::writeBuffered(const uint8_t * buf, uint16_t size) |
Troels Nilsson |
76:eef92651f52f | 533 | { |
Troels Nilsson |
77:a98f786d05d4 | 534 | CriticalSectionLock lock; |
Troels Nilsson |
76:eef92651f52f | 535 | if(!m_terminalConnected && !m_webUSBMode) |
Troels Nilsson |
76:eef92651f52f | 536 | { |
Troels Nilsson |
76:eef92651f52f | 537 | return false; |
Troels Nilsson |
76:eef92651f52f | 538 | } |
Troels Nilsson |
77:a98f786d05d4 | 539 | |
Troels Nilsson |
77:a98f786d05d4 | 540 | m_outputBuffer.queue(buf, size); |
Troels Nilsson |
77:a98f786d05d4 | 541 | if (!m_pendingWrite) |
Troels Nilsson |
76:eef92651f52f | 542 | { |
Troels Nilsson |
77:a98f786d05d4 | 543 | writeToActiveEndpoint(); |
Troels Nilsson |
76:eef92651f52f | 544 | } |
Troels Nilsson |
77:a98f786d05d4 | 545 | else if (m_webUSBMode) |
Troels Nilsson |
76:eef92651f52f | 546 | { |
Troels Nilsson |
77:a98f786d05d4 | 547 | // Check if the write has timed out |
Troels Nilsson |
77:a98f786d05d4 | 548 | if (timeSinceWrite() > WEBUSB_WRITE_TIMEOUT) |
Troels Nilsson |
77:a98f786d05d4 | 549 | { |
Troels Nilsson |
77:a98f786d05d4 | 550 | // Host is no longer reading WebUSB endpoint, assume the client is gone and go back to CDC mode |
Troels Nilsson |
77:a98f786d05d4 | 551 | setWebUSBMode(false); |
Troels Nilsson |
77:a98f786d05d4 | 552 | } |
Troels Nilsson |
76:eef92651f52f | 553 | } |
Troels Nilsson |
77:a98f786d05d4 | 554 | |
Troels Nilsson |
76:eef92651f52f | 555 | return true; |
Troels Nilsson |
76:eef92651f52f | 556 | } |
Troels Nilsson |
76:eef92651f52f | 557 | |
Troels Nilsson |
76:eef92651f52f | 558 | bool USBWebUSBSerial::EPCDC_OUT_callback() |
Troels Nilsson |
76:eef92651f52f | 559 | { |
Troels Nilsson |
76:eef92651f52f | 560 | EPOUTCallbackHandler(EPCDC_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::EPWEBUSB_OUT_callback() |
Troels Nilsson |
76:eef92651f52f | 565 | { |
Troels Nilsson |
76:eef92651f52f | 566 | EPOUTCallbackHandler(EPWEBUSB_OUT); |
Troels Nilsson |
76:eef92651f52f | 567 | return true; |
Troels Nilsson |
76:eef92651f52f | 568 | } |
Troels Nilsson |
76:eef92651f52f | 569 | |
Troels Nilsson |
76:eef92651f52f | 570 | bool USBWebUSBSerial::EPOUTCallbackHandler(uint8_t endpoint) |
Troels Nilsson |
76:eef92651f52f | 571 | { |
Troels Nilsson |
77:a98f786d05d4 | 572 | CriticalSectionLock lock; |
Troels Nilsson |
76:eef92651f52f | 573 | if (endpoint == activeOutEndpoint()) |
Troels Nilsson |
76:eef92651f52f | 574 | { |
Troels Nilsson |
76:eef92651f52f | 575 | return readActiveEP(); |
Troels Nilsson |
76:eef92651f52f | 576 | } |
Troels Nilsson |
76:eef92651f52f | 577 | else |
Troels Nilsson |
76:eef92651f52f | 578 | { |
Troels Nilsson |
76:eef92651f52f | 579 | // Read out the data but ignore it since it is on the inactive endpoint |
Troels Nilsson |
76:eef92651f52f | 580 | uint8_t buffer[MAX_PACKET_SIZE_EPBULK]; |
Troels Nilsson |
76:eef92651f52f | 581 | uint32_t size = 0; |
Troels Nilsson |
76:eef92651f52f | 582 | if (!USBDevice::readEP_NB(endpoint, buffer, &size, MAX_PACKET_SIZE_EPBULK)) |
Troels Nilsson |
76:eef92651f52f | 583 | { |
Troels Nilsson |
76:eef92651f52f | 584 | return false; |
Troels Nilsson |
76:eef92651f52f | 585 | } |
Troels Nilsson |
76:eef92651f52f | 586 | if (!readStart(endpoint, MAX_PACKET_SIZE_EPBULK)) |
Troels Nilsson |
76:eef92651f52f | 587 | { |
Troels Nilsson |
76:eef92651f52f | 588 | return false; |
Troels Nilsson |
76:eef92651f52f | 589 | } |
Troels Nilsson |
76:eef92651f52f | 590 | |
Troels Nilsson |
76:eef92651f52f | 591 | if (size != 0 && endpoint == EPCDC_OUT) |
Troels Nilsson |
76:eef92651f52f | 592 | { |
Troels Nilsson |
76:eef92651f52f | 593 | // terminal must be connected now since we received packets |
Troels Nilsson |
76:eef92651f52f | 594 | m_terminalConnected = true; |
Troels Nilsson |
76:eef92651f52f | 595 | } |
Troels Nilsson |
76:eef92651f52f | 596 | } |
Troels Nilsson |
76:eef92651f52f | 597 | return true; |
Troels Nilsson |
76:eef92651f52f | 598 | } |
Troels Nilsson |
76:eef92651f52f | 599 | |
Troels Nilsson |
77:a98f786d05d4 | 600 | bool USBWebUSBSerial::EPCDC_IN_callback() |
Troels Nilsson |
77:a98f786d05d4 | 601 | { |
Troels Nilsson |
77:a98f786d05d4 | 602 | CriticalSectionLock lock; |
Troels Nilsson |
77:a98f786d05d4 | 603 | if (!m_webUSBMode) |
Troels Nilsson |
77:a98f786d05d4 | 604 | { |
Troels Nilsson |
77:a98f786d05d4 | 605 | writeToActiveEndpoint(); |
Troels Nilsson |
77:a98f786d05d4 | 606 | } |
Troels Nilsson |
77:a98f786d05d4 | 607 | |
Troels Nilsson |
77:a98f786d05d4 | 608 | return true; |
Troels Nilsson |
77:a98f786d05d4 | 609 | } |
Troels Nilsson |
77:a98f786d05d4 | 610 | |
Troels Nilsson |
77:a98f786d05d4 | 611 | bool USBWebUSBSerial::EPWEBUSB_IN_callback() |
Troels Nilsson |
77:a98f786d05d4 | 612 | { |
Troels Nilsson |
77:a98f786d05d4 | 613 | CriticalSectionLock lock; |
Troels Nilsson |
77:a98f786d05d4 | 614 | if (m_webUSBMode) |
Troels Nilsson |
77:a98f786d05d4 | 615 | { |
Troels Nilsson |
77:a98f786d05d4 | 616 | writeToActiveEndpoint(); |
Troels Nilsson |
77:a98f786d05d4 | 617 | } |
Troels Nilsson |
77:a98f786d05d4 | 618 | |
Troels Nilsson |
77:a98f786d05d4 | 619 | return true; |
Troels Nilsson |
77:a98f786d05d4 | 620 | } |
Troels Nilsson |
77:a98f786d05d4 | 621 | |
Troels Nilsson |
76:eef92651f52f | 622 | uint8_t USBWebUSBSerial::available() |
Troels Nilsson |
76:eef92651f52f | 623 | { |
Troels Nilsson |
77:a98f786d05d4 | 624 | CriticalSectionLock lock; |
Troels Nilsson |
77:a98f786d05d4 | 625 | return m_inputBuffer.available(); |
Troels Nilsson |
76:eef92651f52f | 626 | } |
Troels Nilsson |
76:eef92651f52f | 627 | |
Troels Nilsson |
76:eef92651f52f | 628 | void USBWebUSBSerial::setManufacturerName(const std::string &manufacturerName) |
Troels Nilsson |
76:eef92651f52f | 629 | { |
Troels Nilsson |
76:eef92651f52f | 630 | m_manufacturerName = manufacturerName; |
Troels Nilsson |
76:eef92651f52f | 631 | delete m_manufacturerStringDesc; |
Troels Nilsson |
76:eef92651f52f | 632 | m_manufacturerStringDesc = nullptr; |
Troels Nilsson |
76:eef92651f52f | 633 | createDynamicDescriptors(); |
Troels Nilsson |
76:eef92651f52f | 634 | } |
Troels Nilsson |
76:eef92651f52f | 635 | |
Troels Nilsson |
76:eef92651f52f | 636 | void USBWebUSBSerial::setProductName(const std::string &productName) |
Troels Nilsson |
76:eef92651f52f | 637 | { |
Troels Nilsson |
76:eef92651f52f | 638 | m_productName = productName; |
Troels Nilsson |
76:eef92651f52f | 639 | delete m_productStringDesc; |
Troels Nilsson |
76:eef92651f52f | 640 | m_productStringDesc = nullptr; |
Troels Nilsson |
76:eef92651f52f | 641 | createDynamicDescriptors(); |
Troels Nilsson |
76:eef92651f52f | 642 | } |
Troels Nilsson |
76:eef92651f52f | 643 | |
Troels Nilsson |
76:eef92651f52f | 644 | void USBWebUSBSerial::setSerialNumber(const std::string &serialNumber) |
Troels Nilsson |
76:eef92651f52f | 645 | { |
Troels Nilsson |
76:eef92651f52f | 646 | m_serialNumber = serialNumber; |
Troels Nilsson |
76:eef92651f52f | 647 | delete m_serialStringDesc; |
Troels Nilsson |
76:eef92651f52f | 648 | m_serialStringDesc = nullptr; |
Troels Nilsson |
76:eef92651f52f | 649 | createDynamicDescriptors(); |
Troels Nilsson |
76:eef92651f52f | 650 | } |
Troels Nilsson |
76:eef92651f52f | 651 | |
Troels Nilsson |
76:eef92651f52f | 652 | void USBWebUSBSerial::createDynamicDescriptors() |
Troels Nilsson |
76:eef92651f52f | 653 | { |
Troels Nilsson |
76:eef92651f52f | 654 | if (!m_manufacturerStringDesc) |
Troels Nilsson |
76:eef92651f52f | 655 | { |
Troels Nilsson |
76:eef92651f52f | 656 | m_manufacturerStringDesc = createStringDescriptor(m_manufacturerName); |
Troels Nilsson |
76:eef92651f52f | 657 | } |
Troels Nilsson |
76:eef92651f52f | 658 | if (!m_productStringDesc) |
Troels Nilsson |
76:eef92651f52f | 659 | { |
Troels Nilsson |
76:eef92651f52f | 660 | m_productStringDesc = createStringDescriptor(m_productName); |
Troels Nilsson |
76:eef92651f52f | 661 | } |
Troels Nilsson |
76:eef92651f52f | 662 | if (!m_serialStringDesc) |
Troels Nilsson |
76:eef92651f52f | 663 | { |
Troels Nilsson |
76:eef92651f52f | 664 | m_serialStringDesc = createStringDescriptor(m_serialNumber); |
Troels Nilsson |
76:eef92651f52f | 665 | } |
Troels Nilsson |
76:eef92651f52f | 666 | } |
Troels Nilsson |
76:eef92651f52f | 667 | |
Troels Nilsson |
76:eef92651f52f | 668 | uint8_t *USBWebUSBSerial::createStringDescriptor(const std::string &string) const |
Troels Nilsson |
76:eef92651f52f | 669 | { |
Troels Nilsson |
76:eef92651f52f | 670 | uint8_t stringSize = string.size()*2; |
Troels Nilsson |
76:eef92651f52f | 671 | uint8_t descriptorSize = 2 + stringSize; |
Troels Nilsson |
76:eef92651f52f | 672 | uint8_t *descriptor = new uint8_t[descriptorSize]; |
Troels Nilsson |
76:eef92651f52f | 673 | descriptor[0] = descriptorSize; // bLength |
Troels Nilsson |
76:eef92651f52f | 674 | descriptor[1] = STRING_DESCRIPTOR; // bDescriptorType |
Troels Nilsson |
76:eef92651f52f | 675 | for (int i = 0; i < stringSize/2; i++) |
Troels Nilsson |
76:eef92651f52f | 676 | { |
Troels Nilsson |
76:eef92651f52f | 677 | descriptor[(i*2)+2] = string[i]; |
Troels Nilsson |
76:eef92651f52f | 678 | descriptor[(i*2)+3] = 0; |
Troels Nilsson |
76:eef92651f52f | 679 | } |
Troels Nilsson |
76:eef92651f52f | 680 | return descriptor; |
Troels Nilsson |
77:a98f786d05d4 | 681 | } |
Troels Nilsson |
77:a98f786d05d4 | 682 | |
Troels Nilsson |
77:a98f786d05d4 | 683 | void USBWebUSBSerial::setWebUSBMode(bool webUSBMode) |
Troels Nilsson |
77:a98f786d05d4 | 684 | { |
Troels Nilsson |
77:a98f786d05d4 | 685 | CriticalSectionLock lock; |
Troels Nilsson |
77:a98f786d05d4 | 686 | if (webUSBMode != m_webUSBMode) |
Troels Nilsson |
77:a98f786d05d4 | 687 | { |
Troels Nilsson |
77:a98f786d05d4 | 688 | m_webUSBMode = webUSBMode; |
Troels Nilsson |
77:a98f786d05d4 | 689 | m_pendingWrite = false; |
Troels Nilsson |
77:a98f786d05d4 | 690 | |
Troels Nilsson |
77:a98f786d05d4 | 691 | // Clear buffers to clean out any left over data |
Troels Nilsson |
77:a98f786d05d4 | 692 | m_inputBuffer.flush(); |
Troels Nilsson |
77:a98f786d05d4 | 693 | m_outputBuffer.flush(); |
Troels Nilsson |
77:a98f786d05d4 | 694 | } |
Troels Nilsson |
77:a98f786d05d4 | 695 | } |
Troels Nilsson |
77:a98f786d05d4 | 696 | |
Troels Nilsson |
77:a98f786d05d4 | 697 | uint32_t USBWebUSBSerial::timeSinceWrite() const |
Troels Nilsson |
77:a98f786d05d4 | 698 | { |
Troels Nilsson |
77:a98f786d05d4 | 699 | uint32_t currentTime = osKernelGetTickCount(); |
Troels Nilsson |
77:a98f786d05d4 | 700 | if (currentTime < m_lastWriteTime) |
Troels Nilsson |
77:a98f786d05d4 | 701 | { |
Troels Nilsson |
77:a98f786d05d4 | 702 | // Tick count has wrapped around and started from 0 again |
Troels Nilsson |
77:a98f786d05d4 | 703 | return currentTime + (0xFFFFFFFF - m_lastWriteTime); |
Troels Nilsson |
77:a98f786d05d4 | 704 | } |
Troels Nilsson |
77:a98f786d05d4 | 705 | else |
Troels Nilsson |
77:a98f786d05d4 | 706 | { |
Troels Nilsson |
77:a98f786d05d4 | 707 | return currentTime - m_lastWriteTime; |
Troels Nilsson |
77:a98f786d05d4 | 708 | } |
Troels Nilsson |
76:eef92651f52f | 709 | } |