Fork of https://developer.mbed.org/users/bscott/code/STM32_USBDevice/
Fork of STM32_USBDevice by
USBWebUSBSerial.cpp
00001 #include "USBWebUSBSerial.h" 00002 #include "CriticalSectionLock.h" 00003 00004 static uint8_t cdc_line_coding[7]= {0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08}; 00005 00006 #define DEFAULT_CONFIGURATION (1) 00007 00008 #define CDC_SET_LINE_CODING 0x20 00009 #define CDC_GET_LINE_CODING 0x21 00010 #define CDC_SET_CONTROL_LINE_STATE 0x22 00011 00012 // USB standard values 00013 #define USB_CS_INTERFACE 0x24 00014 #define USB_HEADER_FUNCTION_DESCRIPTOR_TYPE 0x00 00015 #define USB_CALL_MANAGEMENT_FUNCTION_DESCRIPTOR_TYPE 0x01 00016 #define USB_ABSTRACT_CONTROL_MANAGEMENT_FUNCTION_DESCRIPTOR_TYPE 0x02 00017 #define USB_UNION_INTERFACE_FUNCTION_DESCRIPTOR_TYPE 0x06 00018 #define PLATFORM_DEVICE_CAPABILITY_TYPE 0x05 00019 00020 #define USB_CDC_CLASS 0x02 00021 #define USB_ACM_SUBCLASS 0x02 00022 #define USB_CDC_DATA_CLASS 0x0A 00023 #define USB_CUSTOM_CLASS 0xFF 00024 00025 // MS OS 2.0 descriptor types 00026 #define MS_OS_20_SET_HEADER_DESCRIPTOR 0x00 00027 #define MS_OS_20_SUBSET_HEADER_CONFIGURATION 0x01 00028 #define MS_OS_20_SUBSET_HEADER_FUNCTION 0x02 00029 #define MS_OS_20_FEATURE_COMPATIBLE_ID 0x03 00030 #define MS_OS_20_FEATURE_REG_PROPERTY 0x04 00031 #define MS_OS_20_FEATURE_MIN_RESUME_TIME 0x05 00032 #define MS_OS_20_FEATURE_MODEL_ID 0x06 00033 #define MS_OS_20_FEATURE_CCGP_DEVICE 0x07 00034 00035 #define MS_OS_20_DESCRIPTOR_INDEX 0x07 00036 #define MS_OS_20_DESCRIPTOR_LENGTH 178 00037 00038 // Vendor commands 00039 #define WINUSB_VENDOR_CODE 0x01 00040 #define SET_WEBUSB_ACTIVE_VENDOR_CODE 0xAA 00041 00042 // Control Line State bits 00043 #define CLS_DTR (1 << 0) 00044 #define CLS_RTS (1 << 1) 00045 00046 #ifdef USB_DEVICE_WRITE_BLOCKING_TIMEOUT_MS 00047 #define WEBUSB_WRITE_TIMEOUT (USB_DEVICE_WRITE_BLOCKING_TIMEOUT_MS) 00048 #else 00049 #define WEBUSB_WRITE_TIMEOUT 1000 00050 #endif 00051 00052 00053 uint8_t USBWebUSBSerial::s_MSOS2Descriptor[] = 00054 { 00055 // Microsoft OS 2.0 descriptor set header (table 10) 00056 0x0A, 0x00, // Header size (always 10 bytes) 00057 LSB(MS_OS_20_SET_HEADER_DESCRIPTOR), 00058 MSB(MS_OS_20_SET_HEADER_DESCRIPTOR), 00059 0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000) 00060 LSB(MS_OS_20_DESCRIPTOR_LENGTH), 00061 MSB(MS_OS_20_DESCRIPTOR_LENGTH), 00062 00063 // Configuration subset header (table 11) 00064 0x08, 0x00, // wLength, always 8 00065 LSB(MS_OS_20_SUBSET_HEADER_CONFIGURATION), 00066 MSB(MS_OS_20_SUBSET_HEADER_CONFIGURATION), 00067 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 00068 0x00, // reserved 00069 LSB(MS_OS_20_DESCRIPTOR_LENGTH - 10), // wTotalLength (length of subset including this header) 00070 MSB(MS_OS_20_DESCRIPTOR_LENGTH - 10), 00071 00072 // Function subset (table 12) 00073 0x08, 0x00, // wLength, always 8 00074 LSB(MS_OS_20_SUBSET_HEADER_FUNCTION), 00075 MSB(MS_OS_20_SUBSET_HEADER_FUNCTION), 00076 0x02, // bFirstInterface 00077 0x00, // reserved 00078 LSB(MS_OS_20_DESCRIPTOR_LENGTH - 18), // wSubSetLength (length of subset including this header) 00079 MSB(MS_OS_20_DESCRIPTOR_LENGTH - 18), 00080 00081 // Microsoft OS 2.0 compatible ID descriptor (table 13) 00082 // Ties the winusb driver to the webusb interface 00083 0x14, 0x00, // wLength, always 20 00084 LSB(MS_OS_20_FEATURE_COMPATIBLE_ID), 00085 MSB(MS_OS_20_FEATURE_COMPATIBLE_ID), 00086 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // CompatibleID (string) 00087 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // SubCompatibleID (string) 00088 00089 // Registry property descriptor (table 14) 00090 // Sets a registry key named DeviceInterfaceGUIDs with a GUID for the WebUSB interface (apparently required before libusb can enumerate it...) 00091 0x84, 0x00, // wLength (132) 00092 LSB(MS_OS_20_FEATURE_REG_PROPERTY), 00093 MSB(MS_OS_20_FEATURE_REG_PROPERTY), 00094 0x07, 0x00, // wPropertyDataType (REG_MULTI_SZ) - see table 15 00095 0x2A, 0x00, // wPropertyNameLength (42) 00096 // Property name (wide string) : DeviceInterfaceGUIDs 00097 '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, 00098 0x50, 0x00, // wPropertyDataLength (80) 00099 // Property data (wide string): {307A82E9-227E-48C3-8C4E-627BE96A7A78} (randomly generated for this device) 00100 '{', 0, '3', 0, '0', 0, '7', 0, 'A', 0, '8', 0, '2', 0, 'E', 0, '9', 0, '-', 0, 00101 '2', 0, '2', 0, '7', 0, 'E', 0, '-', 0, 00102 '4', 0, '8', 0, 'C', 0, '3', 0, '-', 0, 00103 '8', 0, 'C', 0, '4', 0, 'E', 0, '-', 0, 00104 '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 00105 }; 00106 00107 00108 USBWebUSBSerial::USBWebUSBSerial(uint16_t vendor_id, uint16_t product_id, uint16_t product_release, bool connect_blocking) 00109 : USBDevice(vendor_id, product_id, product_release) 00110 { 00111 m_terminalConnected = false; 00112 USBDevice::connect(connect_blocking); 00113 createDynamicDescriptors(); 00114 } 00115 00116 USBWebUSBSerial::~USBWebUSBSerial() 00117 { 00118 delete[] m_manufacturerStringDesc; 00119 delete[] m_productStringDesc; 00120 delete[] m_serialStringDesc; 00121 } 00122 00123 void USBWebUSBSerial::USBCallback_busReset() 00124 { 00125 m_terminalConnected = false; 00126 m_pendingWrite = false; 00127 setWebUSBMode(false); 00128 } 00129 00130 bool USBWebUSBSerial::USBCallback_request() 00131 { 00132 /* Called in ISR context */ 00133 00134 bool success = false; 00135 CONTROL_TRANSFER * transfer = getTransferPtr(); 00136 00137 /* Process class-specific requests */ 00138 if (transfer->setup.bmRequestType.Type == CLASS_TYPE) 00139 { 00140 switch (transfer->setup.bRequest) 00141 { 00142 case CDC_GET_LINE_CODING: 00143 transfer->remaining = 7; 00144 transfer->ptr = cdc_line_coding; 00145 transfer->direction = DEVICE_TO_HOST; 00146 success = true; 00147 break; 00148 case CDC_SET_LINE_CODING: 00149 transfer->remaining = 7; 00150 transfer->notify = true; 00151 success = true; 00152 break; 00153 case CDC_SET_CONTROL_LINE_STATE: 00154 if (transfer->setup.wValue & CLS_DTR) { 00155 m_terminalConnected = true; 00156 } else { 00157 m_terminalConnected = false; 00158 if (!m_webUSBMode) 00159 { 00160 m_pendingWrite = false; 00161 } 00162 } 00163 success = true; 00164 break; 00165 default: 00166 break; 00167 } 00168 } 00169 else if (transfer->setup.bmRequestType.Type == VENDOR_TYPE && transfer->setup.bRequest == WINUSB_VENDOR_CODE && transfer->setup.wIndex == MS_OS_20_DESCRIPTOR_INDEX) 00170 { 00171 // Request for the MS OS 2.0 descriptor 00172 transfer->remaining = MS_OS_20_DESCRIPTOR_LENGTH; 00173 transfer->ptr = s_MSOS2Descriptor; 00174 transfer->direction = DEVICE_TO_HOST; 00175 success = true; 00176 } 00177 else if (transfer->setup.bmRequestType.Type == VENDOR_TYPE && transfer->setup.bRequest == SET_WEBUSB_ACTIVE_VENDOR_CODE) 00178 { 00179 if (transfer->setup.wValue == 0) 00180 { 00181 // Disable WebUSB mode 00182 setWebUSBMode(false); 00183 } 00184 else 00185 { 00186 // Enable WebUSB mode 00187 setWebUSBMode(true); 00188 } 00189 success = true; 00190 } 00191 00192 return success; 00193 } 00194 00195 void USBWebUSBSerial::USBCallback_requestCompleted(uint8_t *buf, uint32_t length) 00196 { 00197 // Request of setting line coding has 7 bytes 00198 if (length != 7) 00199 { 00200 return; 00201 } 00202 00203 CONTROL_TRANSFER * transfer = getTransferPtr(); 00204 00205 /* Process class-specific requests */ 00206 if (transfer->setup.bmRequestType.Type == CLASS_TYPE) 00207 { 00208 if (transfer->setup.bRequest == CDC_SET_LINE_CODING) 00209 { 00210 if (memcmp(cdc_line_coding, buf, 7)) 00211 { 00212 memcpy(cdc_line_coding, buf, 7); 00213 00214 int baud = buf[0] + (buf[1] << 8) 00215 + (buf[2] << 16) + (buf[3] << 24); 00216 int stop = buf[4]; 00217 int bits = buf[6]; 00218 int parity = buf[5]; 00219 00220 lineCodingChanged(baud, bits, parity, stop); 00221 } 00222 } 00223 } 00224 } 00225 00226 // Called in ISR context 00227 // Set configuration. Return false if the 00228 // configuration is not supported. 00229 bool USBWebUSBSerial::USBCallback_setConfiguration(uint8_t configuration) 00230 { 00231 if (configuration != DEFAULT_CONFIGURATION) 00232 { 00233 return false; 00234 } 00235 00236 if (configured()) 00237 { 00238 // Already configured, nothing to do 00239 return true; 00240 } 00241 00242 // Configure endpoints > 0 00243 addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT); 00244 addEndpoint(EPCDC_IN, MAX_PACKET_SIZE_EPBULK); 00245 addEndpoint(EPCDC_OUT, MAX_PACKET_SIZE_EPBULK); 00246 addEndpoint(EPWEBUSB_IN, MAX_PACKET_SIZE_EPBULK); 00247 addEndpoint(EPWEBUSB_OUT, MAX_PACKET_SIZE_EPBULK); 00248 00249 // We activate the endpoints to be able to receive data 00250 readStart(EPCDC_OUT, MAX_PACKET_SIZE_EPBULK); 00251 readStart(EPWEBUSB_OUT, MAX_PACKET_SIZE_EPBULK); 00252 return true; 00253 } 00254 00255 void USBWebUSBSerial::writeToActiveEndpoint() 00256 { 00257 CriticalSectionLock lock; 00258 if(!configured() || m_outputBuffer.isEmpty()) 00259 { 00260 m_pendingWrite = false; 00261 return; 00262 } 00263 00264 uint8_t buffer[MAX_PACKET_SIZE_EPBULK]; 00265 uint16_t size = m_outputBuffer.dequeue(buffer, MAX_PACKET_SIZE_EPBULK); 00266 00267 EP_STATUS result = endpointWrite(activeInEndpoint(), buffer, size); 00268 00269 if (result != EP_PENDING) 00270 { 00271 return; 00272 } 00273 00274 m_lastWriteTime = osKernelGetTickCount(); 00275 m_pendingWrite = true; 00276 } 00277 00278 bool USBWebUSBSerial::readActiveEP() 00279 { 00280 CriticalSectionLock lock; 00281 uint8_t buffer[MAX_PACKET_SIZE_EPBULK]; 00282 uint32_t size = 0; 00283 if (!USBDevice::readEP_NB(activeOutEndpoint(), buffer, &size, MAX_PACKET_SIZE_EPBULK)) 00284 { 00285 return false; 00286 } 00287 if (!readStart(activeOutEndpoint(), MAX_PACKET_SIZE_EPBULK)) 00288 { 00289 return false; 00290 } 00291 00292 m_inputBuffer.queue(buffer, size); 00293 00294 if (size != 0 && activeOutEndpoint() == EPCDC_OUT) 00295 { 00296 // terminal must be connected now since we received packets 00297 m_terminalConnected = true; 00298 } 00299 00300 // call a potential handler 00301 if (m_rx) 00302 { 00303 m_rx.call(); 00304 } 00305 00306 return true; 00307 } 00308 00309 uint8_t * USBWebUSBSerial::deviceDesc() 00310 { 00311 static uint8_t deviceDescriptor[] = { 00312 DEVICE_DESCRIPTOR_LENGTH, // bLength 00313 DEVICE_DESCRIPTOR, // bDescriptorType 00314 0x10, 0x02, // bcdUSB = 2.10 00315 0, // bDeviceClass: composite (unspecified on device level) 00316 0, // bDeviceSubClass 00317 0, // bDeviceProtocol 00318 MAX_PACKET_SIZE_EP0, // bMaxPacketSize0 00319 (uint8_t)(LSB(VENDOR_ID)), (uint8_t)(MSB(VENDOR_ID)), // idVendor 00320 (uint8_t)(LSB(PRODUCT_ID)), (uint8_t)(MSB(PRODUCT_ID)),// idProduct 00321 0x00, 0x01, // bcdDevice 00322 STRING_OFFSET_IMANUFACTURER, // iManufacturer 00323 STRING_OFFSET_IPRODUCT, // iProduct 00324 STRING_OFFSET_ISERIAL, // iSerialNumber 00325 1 // bNumConfigurations 00326 }; 00327 return deviceDescriptor; 00328 } 00329 00330 uint8_t * USBWebUSBSerial::stringImanufacturerDesc() 00331 { 00332 return m_manufacturerStringDesc; 00333 } 00334 00335 uint8_t * USBWebUSBSerial::stringIproductDesc() 00336 { 00337 return m_productStringDesc; 00338 } 00339 00340 uint8_t * USBWebUSBSerial::stringIserialDesc() 00341 { 00342 return m_serialStringDesc; 00343 } 00344 00345 #define CONFIG1_DESC_SIZE (CONFIGURATION_DESCRIPTOR_LENGTH + \ 00346 INTERFACE_ASSOCIATION_DESCRIPTOR_LENGTH + \ 00347 INTERFACE_DESCRIPTOR_LENGTH + \ 00348 5+5+4+5 + \ 00349 ENDPOINT_DESCRIPTOR_LENGTH + \ 00350 INTERFACE_DESCRIPTOR_LENGTH + \ 00351 ENDPOINT_DESCRIPTOR_LENGTH + \ 00352 ENDPOINT_DESCRIPTOR_LENGTH + \ 00353 INTERFACE_DESCRIPTOR_LENGTH + \ 00354 ENDPOINT_DESCRIPTOR_LENGTH + \ 00355 ENDPOINT_DESCRIPTOR_LENGTH) 00356 00357 uint8_t * USBWebUSBSerial::configurationDesc() 00358 { 00359 static uint8_t configDescriptor[] = { 00360 // configuration descriptor 00361 CONFIGURATION_DESCRIPTOR_LENGTH, // bLength 00362 CONFIGURATION_DESCRIPTOR, // bDescriptorType 00363 LSB(CONFIG1_DESC_SIZE), // wTotalLength 00364 MSB(CONFIG1_DESC_SIZE), 00365 3, // bNumInterfaces 00366 1, // bConfigurationValue 00367 0, // iConfiguration 00368 0x80, // bmAttributes 00369 50, // bMaxPower 00370 00371 // IAD to associate the two CDC interfaces 00372 INTERFACE_ASSOCIATION_DESCRIPTOR_LENGTH, // bLength 00373 INTERFACE_ASSOCIATION_DESCRIPTOR, // bDescriptorType 00374 0x00, // bFirstInterface 00375 0x02, // bInterfaceCount 00376 USB_CDC_CLASS, // bFunctionClass 00377 USB_ACM_SUBCLASS, // bFunctionSubClass 00378 0, // bFunctionProtocol 00379 0, // iFunction 00380 00381 // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 00382 INTERFACE_DESCRIPTOR_LENGTH, // bLength 00383 INTERFACE_DESCRIPTOR, // bDescriptorType 00384 0, // bInterfaceNumber 00385 0, // bAlternateSetting 00386 1, // bNumEndpoints 00387 USB_CDC_CLASS, // bInterfaceClass 00388 USB_ACM_SUBCLASS, // bInterfaceSubClass 00389 0x01, // bInterfaceProtocol 00390 0, // iInterface 00391 00392 // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 00393 5, // bFunctionLength 00394 USB_CS_INTERFACE, // bDescriptorType 00395 USB_HEADER_FUNCTION_DESCRIPTOR_TYPE, // bDescriptorSubtype 00396 0x10, 0x01, // bcdCDC 00397 00398 // Call Management Functional Descriptor, CDC PSTN Spec 5.3.1, Table 3 00399 5, // bFunctionLength 00400 USB_CS_INTERFACE, // bDescriptorType 00401 USB_CALL_MANAGEMENT_FUNCTION_DESCRIPTOR_TYPE, // bDescriptorSubtype 00402 0x03, // bmCapabilities 00403 1, // bDataInterface 00404 00405 // Abstract Control Management Functional Descriptor, CDC PSTN Spec 5.3.2, Table 4 00406 4, // bFunctionLength 00407 USB_CS_INTERFACE, // bDescriptorType 00408 USB_ABSTRACT_CONTROL_MANAGEMENT_FUNCTION_DESCRIPTOR_TYPE, // bDescriptorSubtype 00409 0x06, // bmCapabilities 00410 00411 // Union Functional Descriptor, CDC Spec 5.2.3.2, Table 16 00412 5, // bFunctionLength 00413 USB_CS_INTERFACE, // bDescriptorType 00414 USB_UNION_INTERFACE_FUNCTION_DESCRIPTOR_TYPE, // bDescriptorSubtype 00415 0, // bMasterInterface 00416 1, // bSlaveInterface0 00417 00418 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00419 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 00420 ENDPOINT_DESCRIPTOR, // bDescriptorType 00421 PHY_TO_DESC(EPINT_IN), // bEndpointAddress 00422 E_INTERRUPT, // bmAttributes (0x03=intr) 00423 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) 00424 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) 00425 16, // bInterval 00426 00427 // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 00428 INTERFACE_DESCRIPTOR_LENGTH, // bLength 00429 INTERFACE_DESCRIPTOR, // bDescriptorType 00430 1, // bInterfaceNumber 00431 0, // bAlternateSetting 00432 2, // bNumEndpoints 00433 USB_CDC_DATA_CLASS, // bInterfaceClass 00434 0x00, // bInterfaceSubClass 00435 0x00, // bInterfaceProtocol 00436 0, // iInterface 00437 00438 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00439 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 00440 ENDPOINT_DESCRIPTOR, // bDescriptorType 00441 PHY_TO_DESC(EPCDC_IN), // bEndpointAddress 00442 E_BULK, // bmAttributes (0x02=bulk) 00443 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) 00444 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) 00445 0, // bInterval 00446 00447 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00448 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 00449 ENDPOINT_DESCRIPTOR, // bDescriptorType 00450 PHY_TO_DESC(EPCDC_OUT), // bEndpointAddress 00451 E_BULK, // bmAttributes (0x02=bulk) 00452 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) 00453 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) 00454 0, // bInterval 00455 00456 // WebUSB interface 00457 INTERFACE_DESCRIPTOR_LENGTH, // bLength 00458 INTERFACE_DESCRIPTOR, // bDescriptorType 00459 2, // bInterfaceNumber 00460 0, // bAlternateSetting 00461 2, // bNumEndpoints 00462 USB_CUSTOM_CLASS, // bInterfaceClass 00463 0x00, // bInterfaceSubClass 00464 0x00, // bInterfaceProtocol 00465 0, // iInterface 00466 00467 // WebUSB IN endpoint 00468 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 00469 ENDPOINT_DESCRIPTOR, // bDescriptorType 00470 PHY_TO_DESC(EPWEBUSB_IN), // bEndpointAddress 00471 E_BULK, // bmAttributes (0x02=bulk) 00472 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) 00473 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) 00474 0, // bInterval 00475 00476 // WebUSB OUT endpoint 00477 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 00478 ENDPOINT_DESCRIPTOR, // bDescriptorType 00479 PHY_TO_DESC(EPWEBUSB_OUT), // bEndpointAddress 00480 E_BULK, // bmAttributes (0x02=bulk) 00481 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) 00482 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) 00483 0 // bInterval 00484 }; 00485 return configDescriptor; 00486 } 00487 00488 #define BOS_MSOS2_PLATFORM_DESCRIPTOR_LENGTH 28 00489 #define BOS_TOTAL_LENGTH (BOS_DESCRIPTOR_LENGTH + BOS_MSOS2_PLATFORM_DESCRIPTOR_LENGTH) 00490 00491 uint8_t * USBWebUSBSerial::bosDesc() 00492 { 00493 static uint8_t bosDescriptor[] = { 00494 BOS_DESCRIPTOR_LENGTH, // bLength 00495 BOS_DESCRIPTOR, // bDescriptorType 00496 LSB(BOS_TOTAL_LENGTH), // wTotalLength (LSB) 00497 MSB(BOS_TOTAL_LENGTH), // wTotalLength (MSB) 00498 0x01, // bNumDeviceCaps 00499 00500 // MS OS 2.0 descriptors information 00501 BOS_MSOS2_PLATFORM_DESCRIPTOR_LENGTH, 00502 DEVICE_CAPABILITY_DESCRIPTOR, 00503 PLATFORM_DEVICE_CAPABILITY_TYPE, 00504 0x00, // bReserved 00505 0xDF, 0x60, 0xDD, 0xD8, // PlatformCapabilityUUID ({D8DD60DF-4589-4CC7-9CD2-659D9E648A9F}) 00506 0x89, 0x45, 00507 0xC7, 0x4C, 00508 0x9C, 0xD2, 00509 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F, 00510 00511 0x00, 0x00, 0x03, 0x06, // Windows version (8.1 = 0x06030000) 00512 LSB(MS_OS_20_DESCRIPTOR_LENGTH), // wMSOSDecriptorSetTotalLength (LSB) 00513 MSB(MS_OS_20_DESCRIPTOR_LENGTH), // wMSOSDecriptorSetTotalLength (MSB) 00514 WINUSB_VENDOR_CODE, // bMS_VendorCode 00515 0x00 // bAltEnum 00516 }; 00517 return bosDescriptor; 00518 } 00519 00520 int USBWebUSBSerial::read(uint8_t *buf, uint16_t size) 00521 { 00522 CriticalSectionLock lock; 00523 return m_inputBuffer.dequeue(buf, size); 00524 } 00525 00526 bool USBWebUSBSerial::writeBuffered(const uint8_t * buf, uint16_t size) 00527 { 00528 CriticalSectionLock lock; 00529 if(!m_terminalConnected && !m_webUSBMode) 00530 { 00531 return false; 00532 } 00533 00534 m_outputBuffer.queue(buf, size); 00535 if (!m_pendingWrite) 00536 { 00537 writeToActiveEndpoint(); 00538 } 00539 else if (m_webUSBMode) 00540 { 00541 // Check if the write has timed out 00542 if (timeSinceWrite() > WEBUSB_WRITE_TIMEOUT) 00543 { 00544 // Host is no longer reading WebUSB endpoint, assume the client is gone and go back to CDC mode 00545 setWebUSBMode(false); 00546 } 00547 } 00548 00549 return true; 00550 } 00551 00552 bool USBWebUSBSerial::EPCDC_OUT_callback() 00553 { 00554 EPOUTCallbackHandler(EPCDC_OUT); 00555 return true; 00556 } 00557 00558 bool USBWebUSBSerial::EPWEBUSB_OUT_callback() 00559 { 00560 EPOUTCallbackHandler(EPWEBUSB_OUT); 00561 return true; 00562 } 00563 00564 bool USBWebUSBSerial::EPOUTCallbackHandler(uint8_t endpoint) 00565 { 00566 CriticalSectionLock lock; 00567 if (endpoint == activeOutEndpoint()) 00568 { 00569 return readActiveEP(); 00570 } 00571 else 00572 { 00573 // Read out the data but ignore it since it is on the inactive endpoint 00574 uint8_t buffer[MAX_PACKET_SIZE_EPBULK]; 00575 uint32_t size = 0; 00576 if (!USBDevice::readEP_NB(endpoint, buffer, &size, MAX_PACKET_SIZE_EPBULK)) 00577 { 00578 return false; 00579 } 00580 if (!readStart(endpoint, MAX_PACKET_SIZE_EPBULK)) 00581 { 00582 return false; 00583 } 00584 00585 if (size != 0 && endpoint == EPCDC_OUT) 00586 { 00587 // terminal must be connected now since we received packets 00588 m_terminalConnected = true; 00589 } 00590 } 00591 return true; 00592 } 00593 00594 bool USBWebUSBSerial::EPCDC_IN_callback() 00595 { 00596 CriticalSectionLock lock; 00597 if (!m_webUSBMode) 00598 { 00599 writeToActiveEndpoint(); 00600 } 00601 00602 return true; 00603 } 00604 00605 bool USBWebUSBSerial::EPWEBUSB_IN_callback() 00606 { 00607 CriticalSectionLock lock; 00608 if (m_webUSBMode) 00609 { 00610 writeToActiveEndpoint(); 00611 } 00612 00613 return true; 00614 } 00615 00616 uint8_t USBWebUSBSerial::available() 00617 { 00618 CriticalSectionLock lock; 00619 return m_inputBuffer.available(); 00620 } 00621 00622 void USBWebUSBSerial::setManufacturerName(const std::string &manufacturerName) 00623 { 00624 m_manufacturerName = manufacturerName; 00625 delete[] m_manufacturerStringDesc; 00626 m_manufacturerStringDesc = nullptr; 00627 createDynamicDescriptors(); 00628 } 00629 00630 void USBWebUSBSerial::setProductName(const std::string &productName) 00631 { 00632 m_productName = productName; 00633 delete[] m_productStringDesc; 00634 m_productStringDesc = nullptr; 00635 createDynamicDescriptors(); 00636 } 00637 00638 void USBWebUSBSerial::setSerialNumber(const std::string &serialNumber) 00639 { 00640 m_serialNumber = serialNumber; 00641 delete[] m_serialStringDesc; 00642 m_serialStringDesc = nullptr; 00643 createDynamicDescriptors(); 00644 } 00645 00646 void USBWebUSBSerial::createDynamicDescriptors() 00647 { 00648 if (!m_manufacturerStringDesc) 00649 { 00650 m_manufacturerStringDesc = createStringDescriptor(m_manufacturerName); 00651 } 00652 if (!m_productStringDesc) 00653 { 00654 m_productStringDesc = createStringDescriptor(m_productName); 00655 } 00656 if (!m_serialStringDesc) 00657 { 00658 m_serialStringDesc = createStringDescriptor(m_serialNumber); 00659 } 00660 } 00661 00662 uint8_t *USBWebUSBSerial::createStringDescriptor(const std::string &string) const 00663 { 00664 uint8_t stringSize = string.size()*2; 00665 uint8_t descriptorSize = 2 + stringSize; 00666 uint8_t *descriptor = new uint8_t[descriptorSize]; 00667 descriptor[0] = descriptorSize; // bLength 00668 descriptor[1] = STRING_DESCRIPTOR; // bDescriptorType 00669 for (int i = 0; i < stringSize/2; i++) 00670 { 00671 descriptor[(i*2)+2] = string[i]; 00672 descriptor[(i*2)+3] = 0; 00673 } 00674 return descriptor; 00675 } 00676 00677 void USBWebUSBSerial::setWebUSBMode(bool webUSBMode) 00678 { 00679 CriticalSectionLock lock; 00680 if (webUSBMode != m_webUSBMode) 00681 { 00682 m_webUSBMode = webUSBMode; 00683 m_pendingWrite = false; 00684 00685 // Clear buffers to clean out any left over data 00686 m_inputBuffer.flush(); 00687 m_outputBuffer.flush(); 00688 } 00689 } 00690 00691 uint32_t USBWebUSBSerial::timeSinceWrite() const 00692 { 00693 uint32_t currentTime = osKernelGetTickCount(); 00694 if (currentTime < m_lastWriteTime) 00695 { 00696 // Tick count has wrapped around and started from 0 again 00697 return currentTime + (0xFFFFFFFF - m_lastWriteTime); 00698 } 00699 else 00700 { 00701 return currentTime - m_lastWriteTime; 00702 } 00703 }
Generated on Wed Jul 13 2022 00:18:45 by 1.7.2