1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxUsbDevice.hpp
8 
9 Abstract:
10 
11 Author:
12 
13 Environment:
14 
15     kernel mode only
16 
17 Revision History:
18 
19 --*/
20 
21 #ifndef _FXUSBDEVICE_H_
22 #define _FXUSBDEVICE_H_
23 
24 #include "fxusbrequestcontext.hpp"
25 
26 typedef enum _FX_URB_TYPE : UCHAR {
27     FxUrbTypeLegacy,
28     FxUrbTypeUsbdAllocated
29 } FX_URB_TYPE;
30 
31 struct FxUsbDeviceControlContext : public FxUsbRequestContext {
32     FxUsbDeviceControlContext(
33         __in FX_URB_TYPE FxUrbType
34         );
35 
36     ~FxUsbDeviceControlContext(
37         VOID
38         );
39 
40     __checkReturn
41     NTSTATUS
42     AllocateUrb(
43         __in USBD_HANDLE USBDHandle
44         );
45 
46     virtual
47     VOID
48     Dispose(
49         VOID
50         );
51 
52     virtual
53     VOID
54     CopyParameters(
55         __in FxRequestBase* Request
56         );
57 
58     VOID
59     StoreAndReferenceMemory(
60         __in FxUsbDevice* Device,
61         __in FxRequestBuffer* Buffer,
62         __in PWDF_USB_CONTROL_SETUP_PACKET SetupPacket
63         );
64 
65     virtual
66     VOID
67     ReleaseAndRestore(
68         __in FxRequestBase* Request
69         );
70 
71     USBD_STATUS
72     GetUsbdStatus(
73         VOID
74         );
75 
76 private:
77     USBD_HANDLE m_USBDHandle;
78 
79 public:
80 
81     _URB_CONTROL_TRANSFER m_UrbLegacy;
82 
83     //
84     // m_Urb will either point to m_UrbLegacy or one allocated by USBD_UrbAllocate
85     //
86     _URB_CONTROL_TRANSFER* m_Urb;
87 
88     PMDL m_PartialMdl;
89 
90     BOOLEAN m_UnlockPages;
91 };
92 
93 struct FxUsbDeviceStringContext : public FxUsbRequestContext {
94     FxUsbDeviceStringContext(
95         __in FX_URB_TYPE FxUrbType
96         );
97 
98     ~FxUsbDeviceStringContext(
99         VOID
100         );
101 
102     __checkReturn
103     NTSTATUS
104     AllocateUrb(
105         __in USBD_HANDLE USBDHandle
106         );
107 
108     virtual
109     VOID
110     Dispose(
111         VOID
112         );
113 
114     virtual
115     VOID
116     CopyParameters(
117         __in FxRequestBase* Request
118         );
119 
120     VOID
121     SetUrbInfo(
122         __in  UCHAR StringIndex,
123         __in  USHORT LangID
124         );
125 
126     USBD_STATUS
127     GetUsbdStatus(
128         VOID
129         );
130 
131     _Must_inspect_result_
132     NTSTATUS
133     AllocateDescriptor(
134         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
135         __in size_t BufferSize
136         );
137 
138 private:
139     USBD_HANDLE m_USBDHandle;
140 
141 public:
142 
143     _URB_CONTROL_DESCRIPTOR_REQUEST m_UrbLegacy;
144 
145     //
146     // m_Urb will either point to m_UrbLegacy or one allocated by USBD_UrbAllocate
147     //
148     _URB_CONTROL_DESCRIPTOR_REQUEST* m_Urb;
149 
150     PUSB_STRING_DESCRIPTOR m_StringDescriptor;
151 
152     ULONG m_StringDescriptorLength;
153 };
154 
155 class FxUsbUrb : public FxMemoryBufferPreallocated {
156 public:
157 
158     FxUsbUrb(
159         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
160         __in USBD_HANDLE USBDHandle,
161         __in_bcount(BufferSize) PVOID Buffer,
162         __in size_t BufferSize
163         );
164 
165 protected:
166 
167     virtual
168     BOOLEAN
169     Dispose(
170         VOID
171         );
172 
173     ~FxUsbUrb();
174 
175 private:
176 
177     USBD_HANDLE m_USBDHandle;
178 };
179 
180 
181 #define FX_USB_DEVICE_TAG   'sUfD'
182 
183 class FxUsbDevice : public FxIoTarget {
184 public:
185     friend FxUsbPipe;
186     friend FxUsbInterface;
187 
188     FxUsbDevice(
189         __in PFX_DRIVER_GLOBALS FxDriverGlobals
190         );
191 
192     _Must_inspect_result_
193     NTSTATUS
194     InitDevice(
195         __in ULONG USBDClientContractVersionForWdfClient
196         );
197 
198     _Must_inspect_result_
199     NTSTATUS
200     GetConfigDescriptor(
201         __out PVOID ConfigDescriptor,
202         __inout PUSHORT ConfigDescriptorLength
203         );
204 
205     _Must_inspect_result_
206     NTSTATUS
207     GetString(
208         __in_ecount(*NumCharacters) PUSHORT String,
209         __in PUSHORT NumCharacters,
210         __in UCHAR StringIndex,
211         __in_opt USHORT LangID,
212         __in_opt WDFREQUEST Request = NULL,
213         __in_opt PWDF_REQUEST_SEND_OPTIONS Options = NULL
214         );
215 
216     __inline
217     VOID
CopyDeviceDescriptor(__out PUSB_DEVICE_DESCRIPTOR UsbDeviceDescriptor)218     CopyDeviceDescriptor(
219         __out PUSB_DEVICE_DESCRIPTOR UsbDeviceDescriptor
220         )
221     {
222         RtlCopyMemory(UsbDeviceDescriptor,
223                       &m_DeviceDescriptor,
224                       sizeof(m_DeviceDescriptor));
225     }
226 
227     VOID
228     GetInformation(
229         __out PWDF_USB_DEVICE_INFORMATION Information
230         );
231 
232     __inline
233     USBD_CONFIGURATION_HANDLE
GetConfigHandle(VOID)234     GetConfigHandle(
235         VOID
236         )
237     {
238         return m_ConfigHandle;
239     }
240 
241     _Must_inspect_result_
242     __inline
243     NTSTATUS
GetCurrentFrameNumber(__in PULONG Current)244     GetCurrentFrameNumber(
245         __in PULONG Current
246         )
247     {
248         if (m_QueryBusTime != NULL) {
249             return m_QueryBusTime(m_BusInterfaceContext, Current);
250         }
251         else {
252             return STATUS_UNSUCCESSFUL;
253         }
254     }
255 
256     _Must_inspect_result_
257     NTSTATUS
258     SelectConfigAuto(
259         __in PWDF_OBJECT_ATTRIBUTES PipeAttributes
260         );
261 
262     _Must_inspect_result_
263     NTSTATUS
264     SelectConfigInterfaces(
265         __in PWDF_OBJECT_ATTRIBUTES PipesAttributes,
266         __in PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
267         __in_ecount(NumInterfaces)PUSB_INTERFACE_DESCRIPTOR* InterfaceDescriptors,
268         __in ULONG NumInterfaces
269         );
270 
271     _Must_inspect_result_
272     NTSTATUS
273     SelectConfig(
274         __in PWDF_OBJECT_ATTRIBUTES PipesAttributes,
275         __in PURB Urb,
276         __in FX_URB_TYPE FxUrbType,
277         __out_opt PUCHAR NumConfiguredInterfaces
278         );
279 
280     _Must_inspect_result_
281     NTSTATUS
282     Deconfig(
283         VOID
284         );
285 
286     _Must_inspect_result_
287     NTSTATUS
288     SelectInterfaceByInterface(
289         __in PWDF_OBJECT_ATTRIBUTES PipesAttributes,
290         __in PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
291         );
292 
293     _Must_inspect_result_
294     NTSTATUS
295     SelectInterface(
296         __in PWDF_OBJECT_ATTRIBUTES PipesAttributes,
297         __in PURB Urb
298         );
299 
300     UCHAR
GetNumInterfaces(VOID)301     GetNumInterfaces(
302         VOID
303         )
304     {
305         return m_NumInterfaces;
306     }
307 
308     UCHAR
309     GetInterfaceNumEndpoints(
310         __in UCHAR InterfaceNumber
311         );
312 
313     WDFUSBPIPE
314     GetInterfacePipeReferenced(
315         __in UCHAR InterfaceNumber,
316         __in UCHAR EndpointNumber
317         );
318 
319     _Must_inspect_result_
320     NTSTATUS
321     FormatStringRequest(
322         __in FxRequestBase* Request,
323         __in FxRequestBuffer *RequestBuffer,
324         __in  UCHAR StringIndex,
325         __in  USHORT LangID
326         );
327 
328     _Must_inspect_result_
329     NTSTATUS
330     FormatControlRequest(
331         __in FxRequestBase* Request,
332         __in PWDF_USB_CONTROL_SETUP_PACKET Packet,
333         __in FxRequestBuffer *RequestBuffer
334         );
335 
336     _Must_inspect_result_
337     NTSTATUS
338     IsConnected(
339         VOID
340         );
341 
342     _Must_inspect_result_
343     NTSTATUS
344     Reset(
345         VOID
346         );
347 
348     _Must_inspect_result_
349     NTSTATUS
350     CyclePort(
351         VOID
352         );
353 
354     _Must_inspect_result_
355     NTSTATUS
356     FormatCycleRequest(
357         __in FxRequestBase* Request
358         );
359 
360     BOOLEAN
OnUSBD(VOID)361     OnUSBD(
362         VOID
363         )
364     {
365         return m_OnUSBD;
366     }
367 
368     USBD_PIPE_HANDLE
GetControlPipeHandle(VOID)369     GetControlPipeHandle(
370         VOID
371         )
372     {
373         return m_ControlPipe;
374     }
375 
376     _Must_inspect_result_
377     NTSTATUS
378     CreateInterfaces(
379         VOID
380         );
381 
382     _Must_inspect_result_
383     NTSTATUS
384     SelectConfigSingle(
385         __in PWDF_OBJECT_ATTRIBUTES PipeAttributes,
386         __in PWDF_USB_DEVICE_SELECT_CONFIG_PARAMS Params
387         );
388 
389     _Must_inspect_result_
390     NTSTATUS
391     SelectConfigMulti(
392         __in PWDF_OBJECT_ATTRIBUTES PipeAttributes,
393         __in PWDF_USB_DEVICE_SELECT_CONFIG_PARAMS Params
394         );
395 
396     _Must_inspect_result_
397     NTSTATUS
398     SelectConfigDescriptor(
399         __in PWDF_OBJECT_ATTRIBUTES PipeAttributes,
400         __in PWDF_USB_DEVICE_SELECT_CONFIG_PARAMS Params
401         );
402 
403     FxUsbInterface *
404     GetInterfaceFromIndex(
405         __in UCHAR InterfaceIndex
406         );
407 
408     BOOLEAN
HasMismatchedInterfacesInConfigDescriptor(VOID)409     HasMismatchedInterfacesInConfigDescriptor(
410         VOID
411         )
412     {
413         return m_MismatchedInterfacesInConfigDescriptor;
414     }
415 
416     VOID
417     CancelSentIo(
418         VOID
419         );
420 
421     BOOLEAN
422     IsEnabled(
423         VOID
424         );
425 
426     _Must_inspect_result_
427     NTSTATUS
428     QueryUsbCapability(
429         __in
430         CONST GUID* CapabilityType,
431         __in
432         ULONG CapabilityBufferLength,
433         __drv_when(CapabilityBufferLength == 0, __out_opt)
434         __drv_when(CapabilityBufferLength != 0 && ResultLength == NULL, __out_bcount(CapabilityBufferLength))
435         __drv_when(CapabilityBufferLength != 0 && ResultLength != NULL, __out_bcount_part_opt(CapabilityBufferLength, *ResultLength))
436         PVOID CapabilityBuffer,
437         __out_opt
438         __drv_when(ResultLength != NULL,__deref_out_range(<=,CapabilityBufferLength))
439         PULONG ResultLength
440         );
441 
442     __checkReturn
443     NTSTATUS
444     CreateUrb(
445         __in_opt
446         PWDF_OBJECT_ATTRIBUTES Attributes,
447         __out
448         WDFMEMORY* UrbMemory,
449         __deref_opt_out_bcount(sizeof(URB))
450         PURB* Urb
451         );
452 
453 #ifdef _MSC_VER
454 #pragma warning(disable:28285)
455 #endif
456     __checkReturn
457     NTSTATUS
458     CreateIsochUrb(
459         __in_opt
460         PWDF_OBJECT_ATTRIBUTES Attributes,
461         __in
462         ULONG NumberOfIsochPackets,
463         __out
464         WDFMEMORY* UrbMemory,
465         __deref_opt_out_bcount(GET_ISOCH_URB_SIZE(NumberOfIsochPackets))
466         PURB* Urb
467         );
468 
469     USBD_HANDLE
GetUSBDHandle(VOID)470     GetUSBDHandle(
471         VOID
472         )
473     {
474         return m_USBDHandle;
475     }
476 
477     FX_URB_TYPE
GetUrbType(VOID)478     GetUrbType(
479         VOID
480         )
481     {
482         return m_UrbType;
483     }
484 
485     FX_URB_TYPE
486     GetFxUrbTypeForRequest(
487         __in FxRequestBase* Request
488         );
489 
490     BOOLEAN
491     IsObjectDisposedOnRemove(
492         __in FxObject* Object
493         );
494 
495 protected:
496     ~FxUsbDevice(
497         VOID
498         );
499 
500     VOID
501     RemoveDeletedInterface(
502         __in FxUsbInterface* Interface
503         );
504 
505     //
506     // FxIoTarget overrides
507     //
508     virtual
509     _Must_inspect_result_
510     NTSTATUS
511     Start(
512         VOID
513         );
514 
515     virtual
516     VOID
517     Stop(
518         __in WDF_IO_TARGET_SENT_IO_ACTION Action
519         );
520 
521     virtual
522     VOID
523     Purge(
524         __in WDF_IO_TARGET_PURGE_IO_ACTION Action
525         );
526     // end FxIoTarget overrides
527 
528     VOID
529     PipesGotoRemoveState(
530         __in BOOLEAN ForceRemovePipes
531         );
532 
533     static
534     VOID
535     _CleanupPipesRequests(
536         __in PLIST_ENTRY PendHead,
537         __in PSINGLE_LIST_ENTRY SentHead
538         );
539 
540     FxUsbInterface *
541     GetInterfaceFromNumber(
542         __in UCHAR InterfaceNumber
543         );
544 
545     _Must_inspect_result_
546     NTSTATUS
547     GetInterfaceNumberFromInterface(
548         __in WDFUSBINTERFACE UsbInterface,
549         __out PUCHAR InterfaceNumber
550         );
551 
552     VOID
553     CleanupInterfacePipesAndDelete(
554         __in FxUsbInterface * UsbInterface
555         );
556 
_Acquires_lock_(_Global_critical_region_)557     _Acquires_lock_(_Global_critical_region_)
558     VOID
559     AcquireInterfaceIterationLock(
560         VOID
561         )
562     {
563         m_InterfaceIterationLock.AcquireLock(GetDriverGlobals());
564     }
565 
_Releases_lock_(_Global_critical_region_)566     _Releases_lock_(_Global_critical_region_)
567     VOID
568     ReleaseInterfaceIterationLock(
569         VOID
570         )
571     {
572         m_InterfaceIterationLock.ReleaseLock(GetDriverGlobals());
573     }
574 
575     ULONG
576     GetDefaultMaxTransferSize(
577         VOID
578         );
579 
580     VOID
581     FormatInterfaceSelectSettingUrb(
582         __in PURB Urb,
583         __in USHORT NumEndpoints,
584         __in UCHAR InterfaceNumber,
585         __in UCHAR SettingNumber
586         );
587 
588     virtual
589     BOOLEAN
590     Dispose(
591         VOID
592         );
593 
594     _Must_inspect_result_
595     NTSTATUS
596     GetPortStatus(
597         __out PULONG PortStatus
598         );
599 
600 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
601     _Must_inspect_result_
602     NTSTATUS
603     FxUsbDevice::SendSyncRequest(
604         __in FxSyncRequest* Request,
605         __in ULONGLONG Time
606         );
607 
608     _Must_inspect_result_
609     NTSTATUS
610     SendSyncUmUrb(
611         __inout PUMURB Urb,
612         __in ULONGLONG Time,
613         __in_opt WDFREQUEST Request = NULL,
614         __in_opt PWDF_REQUEST_SEND_OPTIONS Options = NULL
615         );
616 #endif
617 
618 protected:
619     USBD_HANDLE m_USBDHandle;
620 
621     USBD_PIPE_HANDLE m_ControlPipe;
622 
623     FxUsbInterface ** m_Interfaces;
624 
625     USBD_CONFIGURATION_HANDLE m_ConfigHandle;
626 
627     USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
628 
629     PUSB_CONFIGURATION_DESCRIPTOR m_ConfigDescriptor;
630 
631     USBD_VERSION_INFORMATION m_UsbdVersionInformation;
632 
633     PUSB_BUSIFFN_QUERY_BUS_TIME m_QueryBusTime;
634 
635     PVOID m_BusInterfaceContext;
636 
637     PINTERFACE_DEREFERENCE m_BusInterfaceDereference;
638 
639     FxWaitLockInternal m_InterfaceIterationLock;
640 
641     ULONG m_HcdPortCapabilities;
642 
643     ULONG m_Traits;
644 
645     BOOLEAN m_OnUSBD;
646 
647     UCHAR m_NumInterfaces;
648 
649     BOOLEAN m_MismatchedInterfacesInConfigDescriptor;
650 
651     FX_URB_TYPE m_UrbType;
652 
653 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
654 private:
655     //
656     // Used to format the IWudfIrp for user-mode requests
657     //
658     IWudfFile* m_pHostTargetFile;
659 
660     //
661     // Handle to the default USB interface exposed by WinUsb
662     //
663     WINUSB_INTERFACE_HANDLE m_WinUsbHandle;
664 #endif
665 };
666 
667 #endif // _FXUSBDEVICE_H_
668