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

Fork of STM32_USBDevice by Bradley Scott

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?

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