@@ -44,7 +44,7 @@ tusb_desc_device_t const desc_device =
4444{
4545 .bLength = sizeof (tusb_desc_device_t ),
4646 .bDescriptorType = TUSB_DESC_DEVICE ,
47- .bcdUSB = 0x0200 ,
47+ .bcdUSB = 0x0201 ,
4848
4949 #if CFG_TUD_CDC
5050 // Use Interface Association Descriptor (IAD) for CDC
@@ -113,6 +113,100 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
113113 return desc_configuration ;
114114}
115115
116+ //--------------------------------------------------------------------+
117+ // BOS Descriptor
118+ //--------------------------------------------------------------------+
119+
120+ /* Microsoft OS 2.0 registry property descriptor
121+ Per MS requirements https://msdn.microsoft.com/en-us/library/windows/hardware/hh450799(v=vs.85).aspx
122+ device should create DeviceInterfaceGUIDs. It can be done by driver and
123+ in case of real PnP solution device should expose MS "Microsoft OS 2.0
124+ registry property descriptor". Such descriptor can insert any record
125+ into Windows registry per device/configuration/interface. In our case it
126+ will insert "DeviceInterfaceGUIDs" multistring property.
127+ GUID is freshly generated and should be OK to use.
128+ https://developers.google.com/web/fundamentals/native-hardware/build-for-webusb/
129+ (Section Microsoft OS compatibility descriptors)
130+ */
131+
132+ #define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN)
133+
134+ #define MS_OS_20_DESC_LEN 0xA2
135+
136+ #define VENDOR_REQUEST_MICROSOFT 1
137+
138+ // BOS Descriptor is required for webUSB
139+ uint8_t const desc_bos [] =
140+ {
141+ // total length, number of device caps
142+ TUD_BOS_DESCRIPTOR (BOS_TOTAL_LEN , 1 ),
143+
144+ // Microsoft OS 2.0 descriptor
145+ TUD_BOS_MS_OS_20_DESCRIPTOR (MS_OS_20_DESC_LEN , 1 )
146+ };
147+
148+ uint8_t const * tud_descriptor_bos_cb (void )
149+ {
150+ return desc_bos ;
151+ }
152+
153+ uint8_t const desc_ms_os_20 [] =
154+ {
155+ // Set header: length, type, windows version, total length
156+ U16_TO_U8S_LE (0x000A ), U16_TO_U8S_LE (MS_OS_20_SET_HEADER_DESCRIPTOR ), U32_TO_U8S_LE (0x06030000 ), U16_TO_U8S_LE (MS_OS_20_DESC_LEN ),
157+
158+ // MS OS 2.0 Compatible ID descriptor: length, type, compatible ID, sub compatible ID
159+ U16_TO_U8S_LE (0x0014 ), U16_TO_U8S_LE (MS_OS_20_FEATURE_COMPATBLE_ID ), 'W' , 'I' , 'N' , 'U' , 'S' , 'B' , 0x00 , 0x00 ,
160+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , // sub-compatible
161+
162+ // MS OS 2.0 Registry property descriptor: length, type
163+ U16_TO_U8S_LE (MS_OS_20_DESC_LEN - 0x0A - 0x14 ), U16_TO_U8S_LE (MS_OS_20_FEATURE_REG_PROPERTY ),
164+ U16_TO_U8S_LE (0x0007 ), U16_TO_U8S_LE (0x002A ), // wPropertyDataType, wPropertyNameLength and PropertyName "DeviceInterfaceGUIDs\0" in UTF-16
165+ 'D' , 0x00 , 'e' , 0x00 , 'v' , 0x00 , 'i' , 0x00 , 'c' , 0x00 , 'e' , 0x00 , 'I' , 0x00 , 'n' , 0x00 , 't' , 0x00 , 'e' , 0x00 ,
166+ 'r' , 0x00 , 'f' , 0x00 , 'a' , 0x00 , 'c' , 0x00 , 'e' , 0x00 , 'G' , 0x00 , 'U' , 0x00 , 'I' , 0x00 , 'D' , 0x00 , 's' , 0x00 , 0x00 , 0x00 ,
167+ U16_TO_U8S_LE (0x0050 ), // wPropertyDataLength
168+ //bPropertyData: {3E7E0711-DF3B-4158-A32F-E5951B2AB9A1}.
169+ '{' , 0x00 , '3' , 0x00 , 'E' , 0x00 , '7' , 0x00 , 'E' , 0x00 , '0' , 0x00 , '7' , 0x00 , '1' , 0x00 , '1' , 0x00 , '-' , 0x00 ,
170+ 'D' , 0x00 , 'F' , 0x00 , '3' , 0x00 , 'B' , 0x00 , '-' , 0x00 , '4' , 0x00 , '1' , 0x00 , '5' , 0x00 , '8' , 0x00 , '-' , 0x00 ,
171+ 'A' , 0x00 , '3' , 0x00 , '2' , 0x00 , 'F' , 0x00 , '-' , 0x00 , 'E' , 0x00 , '5' , 0x00 , '9' , 0x00 , '5' , 0x00 , '1' , 0x00 ,
172+ 'B' , 0x00 , '2' , 0x00 , 'A' , 0x00 , 'B' , 0x00 , '9' , 0x00 , 'A' , 0x00 , '1' , 0x00 , '}' , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
173+ };
174+
175+ TU_VERIFY_STATIC (sizeof (desc_ms_os_20 ) == MS_OS_20_DESC_LEN , "Incorrect size" );
176+
177+ // Invoked when a control transfer occurred on an interface of this class
178+ // Driver response accordingly to the request and the transfer stage (setup/data/ack)
179+ // return false to stall control endpoint (e.g unsupported request)
180+ bool tud_vendor_control_xfer_cb (uint8_t rhport , uint8_t stage , tusb_control_request_t const * request )
181+ {
182+ // nothing to with DATA & ACK stage
183+ if (stage != CONTROL_STAGE_SETUP ) return true;
184+
185+ switch (request -> bmRequestType_bit .type )
186+ {
187+ case TUSB_REQ_TYPE_VENDOR :
188+ switch (request -> bRequest )
189+ {
190+ case VENDOR_REQUEST_MICROSOFT :
191+ if ( request -> wIndex == 7 )
192+ {
193+ return tud_control_xfer (rhport , request , (void * ) desc_ms_os_20 , MS_OS_20_DESC_LEN );
194+ }else
195+ {
196+ return false;
197+ }
198+
199+ default : break ;
200+ }
201+ break ;
202+
203+ default : break ;
204+ }
205+
206+ // stall unknown request
207+ return false;
208+ }
209+
116210//--------------------------------------------------------------------+
117211// String Descriptors
118212//--------------------------------------------------------------------+
0 commit comments