1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxUsbInterfaceAPI.cpp
8 
9 Abstract:
10 
11 
12 Author:
13 
14 Environment:
15 
16     Both kernel and user mode
17 
18 Revision History:
19 
20 --*/
21 #include "fxusbpch.hpp"
22 
23 extern "C" {
24 #include "FxUsbInterfaceAPI.tmh"
25 }
26 
27 //
28 // Extern "C" all APIs
29 //
30 extern "C" {
31 
32 _Must_inspect_result_
33 __drv_maxIRQL(PASSIVE_LEVEL)
34 NTSTATUS
35 WDFAPI
36 WDFEXPORT(WdfUsbInterfaceSelectSetting)(
37     __in
38     PWDF_DRIVER_GLOBALS DriverGlobals,
39     __in
40     WDFUSBINTERFACE UsbInterface,
41     __in_opt
42     PWDF_OBJECT_ATTRIBUTES PipesAttributes,
43     __in
44     PWDF_USB_INTERFACE_SELECT_SETTING_PARAMS Params
45     )
46 /*++
47 
48 Routine Description:
49     Selects an alternate setting on a given interface number
50 
51 Arguments:
52     UsbInterface - the interface whose setting will be selected
53 
54     PipesAttributes - Attributes to apply to each of the new pipes on the setting
55 
56     Params - Strucutre indicating how to select a new setting
57 
58 Return Value:
59     NTSTATUS
60 
61   --*/
62 {
63     DDI_ENTRY();
64 
65     PFX_DRIVER_GLOBALS pFxDriverGlobals;
66     FxUsbInterface* pUsbInterface;
67     NTSTATUS status;
68 
69     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
70                                    UsbInterface,
71                                    FX_TYPE_USB_INTERFACE,
72                                    (PVOID*) &pUsbInterface,
73                                    &pFxDriverGlobals);
74 
75     FxPointerNotNull(pFxDriverGlobals, Params);
76 
77     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
78     if (!NT_SUCCESS(status)) {
79         return status;
80     }
81 
82     if (Params->Size != sizeof(WDF_USB_INTERFACE_SELECT_SETTING_PARAMS)) {
83         status = STATUS_INFO_LENGTH_MISMATCH;
84         DoTraceLevelMessage(
85             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
86             "Params size %d, expected %d %!STATUS!", Params->Size,
87             sizeof(WDF_USB_INTERFACE_SELECT_SETTING_PARAMS), status);
88         return status;
89     }
90 
91     status = FxValidateObjectAttributes(pFxDriverGlobals,
92                                         PipesAttributes,
93                                         FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
94     if (!NT_SUCCESS(status)) {
95         return status;
96     }
97 
98 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
99     if (Params->Type != WdfUsbInterfaceSelectSettingTypeSetting) {
100         FX_VERIFY_WITH_NAME(INTERNAL, TRAPMSG("UMDF may only select settings by index."),
101             DriverGlobals->DriverName);
102     }
103 #endif
104 
105     switch (Params->Type) {
106     case WdfUsbInterfaceSelectSettingTypeDescriptor:
107         if (Params->Types.Descriptor.InterfaceDescriptor == NULL) {
108             status = STATUS_INVALID_PARAMETER;
109             DoTraceLevelMessage(
110                 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
111                 "InterfaceDescriptor passed in is NULL %!STATUS!", status);
112 
113         }
114         else {
115             status = pUsbInterface->SelectSettingByDescriptor(
116                 PipesAttributes,
117                 Params->Types.Descriptor.InterfaceDescriptor
118                 );
119         }
120         break;
121 
122     case WdfUsbInterfaceSelectSettingTypeSetting:
123         status = pUsbInterface->SelectSettingByIndex(
124             PipesAttributes,
125             Params->Types.Interface.SettingIndex
126             );
127         break;
128 
129     case WdfUsbInterfaceSelectSettingTypeUrb:
130         if (Params->Types.Urb.Urb == NULL ||
131             Params->Types.Urb.Urb->UrbHeader.Function != URB_FUNCTION_SELECT_INTERFACE ||
132             (Params->Types.Urb.Urb->UrbHeader.Length  <
133             sizeof(struct _URB_SELECT_INTERFACE) - sizeof(USBD_PIPE_INFORMATION)) ) {
134             status = STATUS_INVALID_PARAMETER;
135             DoTraceLevelMessage(
136                 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
137                 "URB or URB fields passed in are invalid Urb 0x%p  %!STATUS!",
138                 Params->Types.Urb.Urb, status);
139 
140         }
141         else {
142             status = pUsbInterface->SelectSetting(PipesAttributes,
143                                                  Params->Types.Urb.Urb);
144         }
145         break;
146 
147     default:
148         status = STATUS_INVALID_PARAMETER;
149         break;
150     }
151 
152     return status;
153 }
154 
155 
156 __drv_maxIRQL(DISPATCH_LEVEL)
157 BYTE
158 WDFAPI
159 WDFEXPORT(WdfUsbInterfaceGetInterfaceNumber)(
160     __in
161     PWDF_DRIVER_GLOBALS DriverGlobals,
162     __in
163     WDFUSBINTERFACE UsbInterface
164     )
165 /*++
166 
167 Routine Description:
168     Returns the interface number of the given interface.  The interface number
169     is not necessarily the same as the index of the interface.  Once is specified
170     by the device, the other is where it is located within an internal array.
171 
172 Arguments:
173     UsbInterface - Interace whose number will be returned
174 
175 Return Value:
176     interface number
177 
178   --*/
179 {
180     DDI_ENTRY();
181 
182     FxUsbInterface * pUsbInterface;
183 
184     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
185                          UsbInterface,
186                          FX_TYPE_USB_INTERFACE,
187                          (PVOID*) &pUsbInterface);
188 
189     return pUsbInterface->GetInterfaceNumber();
190 }
191 
192 __drv_maxIRQL(DISPATCH_LEVEL)
193 BYTE
194 WDFAPI
195 WDFEXPORT(WdfUsbInterfaceGetNumEndpoints)(
196     __in
197     PWDF_DRIVER_GLOBALS DriverGlobals,
198     __in
199     WDFUSBINTERFACE UsbInterface,
200     __in
201     UCHAR SettingIndex
202     )
203 /*++
204 
205 Routine Description:
206     Returns the number of endpoints (not configured) for a given setting on the
207     given interface.
208 
209 Arguments:
210     UsbInterface - interface whose number of endpoints will be returned
211 
212     SettingsIndex - the index into the alternate setting array
213 
214 Return Value:
215     Number of endpoints
216 
217   --*/
218 {
219     DDI_ENTRY();
220 
221     FxUsbInterface * pUsbInterface;
222 
223     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
224                          UsbInterface,
225                          FX_TYPE_USB_INTERFACE  ,
226                          (PVOID*) &pUsbInterface);
227 
228     return pUsbInterface->GetNumEndpoints(SettingIndex);
229 }
230 
231 __drv_maxIRQL(DISPATCH_LEVEL)
232 VOID
233 WDFAPI
234 WDFEXPORT(WdfUsbInterfaceGetEndpointInformation)(
235     __in
236     PWDF_DRIVER_GLOBALS DriverGlobals,
237     __in
238     WDFUSBINTERFACE UsbInterface,
239     __in
240     UCHAR SettingIndex,
241     __in
242     UCHAR EndpointIndex,
243     __out
244     PWDF_USB_PIPE_INFORMATION EndpointInfo
245     )
246 /*++
247 
248 Routine Description:
249     Returns information on a given endpoint (unconfigured) for an interface +
250     alternate setting index.
251 
252 Arguments:
253     UsbInterface - interface which contains  the endpoint
254 
255     SettingIndex - alternate setting index
256 
257     EndpointIndex - index into the endpoint array contained by interface+setting
258 
259     EndpointInfo - structure to be filled in with the info of the endpoint
260 
261 Return Value:
262     None
263 
264   --*/
265 {
266     DDI_ENTRY();
267 
268     PFX_DRIVER_GLOBALS pFxDriverGlobals;
269     FxUsbInterface * pUsbInterface;
270 
271     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
272                                    UsbInterface,
273                                    FX_TYPE_USB_INTERFACE,
274                                    (PVOID*) &pUsbInterface,
275                                    &pFxDriverGlobals);
276 
277     FxPointerNotNull(pFxDriverGlobals, EndpointInfo);
278 
279     if (EndpointInfo->Size != sizeof(WDF_USB_PIPE_INFORMATION)) {
280         DoTraceLevelMessage(
281             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
282             "EndpointInfo Size %d incorrect, expected %d, %!STATUS!",
283             EndpointInfo->Size, sizeof(WDF_USB_PIPE_INFORMATION),
284             STATUS_INFO_LENGTH_MISMATCH);
285         FxVerifierDbgBreakPoint(pFxDriverGlobals);
286         return;
287     }
288 
289     pUsbInterface->GetEndpointInformation(SettingIndex,
290                                           EndpointIndex,
291                                           EndpointInfo);
292 }
293 
294 __drv_maxIRQL(DISPATCH_LEVEL)
295 BYTE
296 WDFEXPORT(WdfUsbInterfaceGetNumSettings)(
297     __in
298     PWDF_DRIVER_GLOBALS DriverGlobals,
299     __in
300     WDFUSBINTERFACE UsbInterface
301     )
302 /*++
303 
304 Routine Description:
305     Returns the number of settings available on an interface.
306 
307 Arguments:
308     UsbInterface - the usb interface being queried
309 
310 Return Value:
311     Number of settings  as described by the config descriptor
312 
313   --*/
314 {
315     DDI_ENTRY();
316 
317     FxUsbInterface * pUsbInterface;
318 
319     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
320                          UsbInterface,
321                          FX_TYPE_USB_INTERFACE,
322                          (PVOID*) &pUsbInterface);
323 
324     return pUsbInterface->GetNumSettings();
325 }
326 
327 __drv_maxIRQL(DISPATCH_LEVEL)
328 VOID
329 WDFAPI
330 WDFEXPORT(WdfUsbInterfaceGetDescriptor)(
331     __in
332     PWDF_DRIVER_GLOBALS DriverGlobals,
333     __in
334     WDFUSBINTERFACE UsbInterface,
335     __in
336     UCHAR SettingIndex,
337     __out
338     PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
339     )
340 /*++
341 
342 Routine Description:
343     Returns the underlying USB interface descriptor for the given WDF handle
344 
345 Arguments:
346     UsbInterface - interface whose descriptor will be returned
347 
348     SettingIndex - alternatve setting whose interface should be returned
349 
350     InterfaceDescriptor - Pointer which will receive the descriptor
351 
352   --*/
353 {
354     DDI_ENTRY();
355 
356     PFX_DRIVER_GLOBALS pFxDriverGlobals;
357     FxUsbInterface * pUsbInterface;
358 
359     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
360                                    UsbInterface,
361                                    FX_TYPE_USB_INTERFACE,
362                                    (PVOID*) &pUsbInterface,
363                                    &pFxDriverGlobals);
364 
365     FxPointerNotNull(pFxDriverGlobals, InterfaceDescriptor);
366 
367     pUsbInterface->GetDescriptor(InterfaceDescriptor, SettingIndex);
368 }
369 
370 __drv_maxIRQL(DISPATCH_LEVEL)
371 BYTE
372 WDFAPI
373 WDFEXPORT(WdfUsbInterfaceGetConfiguredSettingIndex)(
374     __in
375     PWDF_DRIVER_GLOBALS DriverGlobals,
376     __in
377     WDFUSBINTERFACE UsbInterface
378     )
379 /*++
380 
381 Routine Description:
382     Returns the alternate setting index which is currently configured
383 
384 Arguments:
385     UsbInterface - interfase whose configured setting is being queried
386 
387 Return Value:
388     The current setting or 0 on failure
389 
390   --*/
391 {
392     DDI_ENTRY();
393 
394     FxUsbInterface * pUsbInterface;
395 
396     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
397                          UsbInterface,
398                          FX_TYPE_USB_INTERFACE  ,
399                          (PVOID*) &pUsbInterface);
400 
401     return pUsbInterface->GetConfiguredSettingIndex();
402 }
403 
404 __drv_maxIRQL(DISPATCH_LEVEL)
405 BYTE
406 WDFAPI
407 WDFEXPORT(WdfUsbInterfaceGetNumConfiguredPipes)(
408     __in
409     PWDF_DRIVER_GLOBALS DriverGlobals,
410     __in
411     WDFUSBINTERFACE  UsbInterface
412     )
413 /*++
414 
415 Routine Description:
416     Returns the number of configured pipes on a given interface.
417 
418 Arguments:
419     UsbInterface - the configured interface
420 
421 Return Value:
422     Number of configured pipes or 0 on error
423 
424   --*/
425 {
426     DDI_ENTRY();
427 
428     FxUsbInterface * pUsbInterface;
429 
430     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
431                          UsbInterface,
432                          FX_TYPE_USB_INTERFACE  ,
433                          (PVOID*) &pUsbInterface);
434 
435     return pUsbInterface->GetNumConfiguredPipes();
436 }
437 
438 __drv_maxIRQL(DISPATCH_LEVEL)
439 WDFUSBPIPE
440 WDFAPI
441 WDFEXPORT(WdfUsbInterfaceGetConfiguredPipe)(
442     __in
443     PWDF_DRIVER_GLOBALS DriverGlobals,
444     __in
445     WDFUSBINTERFACE UsbInterface,
446     __in
447     UCHAR PipeIndex,
448     __out_opt
449     PWDF_USB_PIPE_INFORMATION PipeInfo
450     )
451 /*++
452 
453 Routine Description:
454     Returns the WDFUSBPIPE handle for the configured interface + pipe index.
455     Optionally, information about the pipe is also returned.
456 
457 Arguments:
458     UsbInterface  - configured interface
459 
460     PipeIndex - index into the number of pipes on the interface
461 
462     PipeInfo - information to be returned on the pipe
463 
464 Return Value:
465     valid WDFUSBPIPE or NULL on error
466 
467   --*/
468 {
469     DDI_ENTRY();
470 
471     PFX_DRIVER_GLOBALS pFxDriverGlobals;
472     FxUsbInterface * pUsbInterface;
473     NTSTATUS status;
474 
475     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
476                                    UsbInterface,
477                                    FX_TYPE_USB_INTERFACE,
478                                    (PVOID*) &pUsbInterface,
479                                    &pFxDriverGlobals);
480 
481     if (PipeInfo != NULL && PipeInfo->Size != sizeof(WDF_USB_PIPE_INFORMATION)) {
482         status = STATUS_INFO_LENGTH_MISMATCH;
483 
484         DoTraceLevelMessage(
485             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
486             "PipeInfo Size %d incorrect, expected %d, %!STATUS!",
487             PipeInfo->Size, sizeof(WDF_USB_PIPE_INFORMATION), status);
488 
489         FxVerifierDbgBreakPoint(pFxDriverGlobals);
490 
491         return NULL;
492     }
493 
494     return pUsbInterface->GetConfiguredPipe(PipeIndex, PipeInfo);
495 }
496 
497 } // extern "C"
498