Fork of https://developer.mbed.org/users/bscott/code/STM32_USBDevice/

Fork of STM32_USBDevice by Bradley Scott

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?

UserRevisionLine numberNew 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 }