18a978a17SVictor Perevertkin /*++
28a978a17SVictor Perevertkin 
38a978a17SVictor Perevertkin Copyright (c) Microsoft Corporation
48a978a17SVictor Perevertkin 
58a978a17SVictor Perevertkin Module Name:
68a978a17SVictor Perevertkin 
78a978a17SVictor Perevertkin     FxUsbDeviceKm.cpp
88a978a17SVictor Perevertkin 
98a978a17SVictor Perevertkin Abstract:
108a978a17SVictor Perevertkin 
118a978a17SVictor Perevertkin Author:
128a978a17SVictor Perevertkin 
138a978a17SVictor Perevertkin Environment:
148a978a17SVictor Perevertkin 
158a978a17SVictor Perevertkin     kernel mode only
168a978a17SVictor Perevertkin 
178a978a17SVictor Perevertkin Revision History:
188a978a17SVictor Perevertkin 
198a978a17SVictor Perevertkin --*/
208a978a17SVictor Perevertkin 
218a978a17SVictor Perevertkin extern "C" {
228a978a17SVictor Perevertkin #include <initguid.h>
238a978a17SVictor Perevertkin }
248a978a17SVictor Perevertkin 
258a978a17SVictor Perevertkin #include "fxusbpch.hpp"
268a978a17SVictor Perevertkin 
278a978a17SVictor Perevertkin 
288a978a17SVictor Perevertkin extern "C" {
298a978a17SVictor Perevertkin #include "FxUsbDeviceKm.tmh"
308a978a17SVictor Perevertkin }
318a978a17SVictor Perevertkin 
328a978a17SVictor Perevertkin 
338a978a17SVictor Perevertkin 
348a978a17SVictor Perevertkin 
358a978a17SVictor Perevertkin 
368a978a17SVictor Perevertkin 
378a978a17SVictor Perevertkin 
388a978a17SVictor Perevertkin #define UCHAR_MAX (0xff)
398a978a17SVictor Perevertkin 
408a978a17SVictor Perevertkin 
418a978a17SVictor Perevertkin _Must_inspect_result_
428a978a17SVictor Perevertkin NTSTATUS
InitDevice(__in ULONG USBDClientContractVersionForWdfClient)438a978a17SVictor Perevertkin FxUsbDevice::InitDevice(
448a978a17SVictor Perevertkin     __in ULONG USBDClientContractVersionForWdfClient
458a978a17SVictor Perevertkin     )
468a978a17SVictor Perevertkin {
478a978a17SVictor Perevertkin     URB urb;
488a978a17SVictor Perevertkin     FxSyncRequest request(GetDriverGlobals(), NULL);
498a978a17SVictor Perevertkin     WDF_REQUEST_SEND_OPTIONS options;
508a978a17SVictor Perevertkin     NTSTATUS status;
518a978a17SVictor Perevertkin     ULONG size;
528a978a17SVictor Perevertkin 
538a978a17SVictor Perevertkin     RtlZeroMemory(&urb, sizeof(urb));
548a978a17SVictor Perevertkin 
558a978a17SVictor Perevertkin     if (USBDClientContractVersionForWdfClient != USBD_CLIENT_CONTRACT_VERSION_INVALID) {
568a978a17SVictor Perevertkin 
578a978a17SVictor Perevertkin         //
588a978a17SVictor Perevertkin         // Register with USBDEX.lib
598a978a17SVictor Perevertkin         //
608a978a17SVictor Perevertkin         status = USBD_CreateHandle(m_InStackDevice,
618a978a17SVictor Perevertkin                                    m_TargetDevice,
628a978a17SVictor Perevertkin                                    USBDClientContractVersionForWdfClient,
638a978a17SVictor Perevertkin                                    GetDriverGlobals()->Tag,
648a978a17SVictor Perevertkin                                    &m_USBDHandle);
658a978a17SVictor Perevertkin 
668a978a17SVictor Perevertkin         if (!NT_SUCCESS(status)) {
678a978a17SVictor Perevertkin             DoTraceLevelMessage(
688a978a17SVictor Perevertkin                 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
698a978a17SVictor Perevertkin                 "USBD_CreateHandle failed, %!STATUS!", status);
708a978a17SVictor Perevertkin             goto Done;
718a978a17SVictor Perevertkin         }
728a978a17SVictor Perevertkin 
738a978a17SVictor Perevertkin         m_UrbType = FxUrbTypeUsbdAllocated;
748a978a17SVictor Perevertkin     }
758a978a17SVictor Perevertkin 
768a978a17SVictor Perevertkin     status = request.m_TrueRequest->ValidateTarget(this);
778a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
788a978a17SVictor Perevertkin         goto Done;
798a978a17SVictor Perevertkin     }
808a978a17SVictor Perevertkin 
818a978a17SVictor Perevertkin     UsbBuildGetDescriptorRequest(&urb,
828a978a17SVictor Perevertkin                                  sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
838a978a17SVictor Perevertkin                                  USB_DEVICE_DESCRIPTOR_TYPE,
848a978a17SVictor Perevertkin                                  0,
858a978a17SVictor Perevertkin                                  0,
868a978a17SVictor Perevertkin                                  &m_DeviceDescriptor,
878a978a17SVictor Perevertkin                                  NULL,
888a978a17SVictor Perevertkin                                  sizeof(m_DeviceDescriptor),
898a978a17SVictor Perevertkin                                  NULL);
908a978a17SVictor Perevertkin 
918a978a17SVictor Perevertkin     FxFormatUsbRequest(request.m_TrueRequest, &urb, FxUrbTypeLegacy, NULL);
928a978a17SVictor Perevertkin 
938a978a17SVictor Perevertkin     WDF_REQUEST_SEND_OPTIONS_INIT(&options, 0);
948a978a17SVictor Perevertkin     WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&options, WDF_REL_TIMEOUT_IN_SEC(5));
958a978a17SVictor Perevertkin 
968a978a17SVictor Perevertkin     status = SubmitSync(request.m_TrueRequest, &options);
978a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
988a978a17SVictor Perevertkin         DoTraceLevelMessage(
998a978a17SVictor Perevertkin             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1008a978a17SVictor Perevertkin             "Could not retrieve device descriptor, %!STATUS!", status);
1018a978a17SVictor Perevertkin         goto Done;
1028a978a17SVictor Perevertkin     }
1038a978a17SVictor Perevertkin 
1048a978a17SVictor Perevertkin     //
1058a978a17SVictor Perevertkin     // After successfully completing any default control URB, USBD/usbport fills
1068a978a17SVictor Perevertkin     // in the PipeHandle field of the URB (it is the same offset in every URB,
1078a978a17SVictor Perevertkin     // which this CASSERT verifies.  Since USBD_DEFAULT_PIPE_TRANSFER is not
1088a978a17SVictor Perevertkin     // supported by USBD (it is by USBPORT), this is the prescribed way of getting
1098a978a17SVictor Perevertkin     // the default control pipe so that you can set the PipeHandle field in
1108a978a17SVictor Perevertkin     // _URB_CONTROL_TRANSFER.
1118a978a17SVictor Perevertkin     //
1128a978a17SVictor Perevertkin     WDFCASSERT(FIELD_OFFSET(_URB_CONTROL_TRANSFER, PipeHandle) ==
1138a978a17SVictor Perevertkin                FIELD_OFFSET(_URB_CONTROL_DESCRIPTOR_REQUEST, Reserved));
1148a978a17SVictor Perevertkin 
1158a978a17SVictor Perevertkin     m_ControlPipe = urb.UrbControlDescriptorRequest.Reserved;
1168a978a17SVictor Perevertkin 
1178a978a17SVictor Perevertkin     USB_CONFIGURATION_DESCRIPTOR config;
1188a978a17SVictor Perevertkin 
1198a978a17SVictor Perevertkin     RtlZeroMemory(&config, sizeof(config));
1208a978a17SVictor Perevertkin     size = sizeof(config);
1218a978a17SVictor Perevertkin 
1228a978a17SVictor Perevertkin     UsbBuildGetDescriptorRequest(&urb,
1238a978a17SVictor Perevertkin                                  sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST),
1248a978a17SVictor Perevertkin                                  USB_CONFIGURATION_DESCRIPTOR_TYPE,
1258a978a17SVictor Perevertkin                                  0,
1268a978a17SVictor Perevertkin                                  0,
1278a978a17SVictor Perevertkin                                  &config,
1288a978a17SVictor Perevertkin                                  NULL,
1298a978a17SVictor Perevertkin                                  size,
1308a978a17SVictor Perevertkin                                  NULL);
1318a978a17SVictor Perevertkin 
1328a978a17SVictor Perevertkin     request.m_TrueRequest->GetSubmitFxIrp()->Reuse(STATUS_SUCCESS);
1338a978a17SVictor Perevertkin     request.m_TrueRequest->ClearFieldsForReuse();
1348a978a17SVictor Perevertkin     FxFormatUsbRequest(request.m_TrueRequest, &urb, FxUrbTypeLegacy, NULL);
1358a978a17SVictor Perevertkin 
1368a978a17SVictor Perevertkin     status = SubmitSync(request.m_TrueRequest, &options);
1378a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
1388a978a17SVictor Perevertkin         DoTraceLevelMessage(
1398a978a17SVictor Perevertkin             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1408a978a17SVictor Perevertkin             "Could not retrieve config descriptor size, %!STATUS!", status);
1418a978a17SVictor Perevertkin         goto Done;
1428a978a17SVictor Perevertkin     }
1438a978a17SVictor Perevertkin     else if (urb.UrbControlDescriptorRequest.TransferBufferLength == 0) {
1448a978a17SVictor Perevertkin         //
1458a978a17SVictor Perevertkin         // Not enough info returned
1468a978a17SVictor Perevertkin         //
1478a978a17SVictor Perevertkin         status = STATUS_UNSUCCESSFUL;
1488a978a17SVictor Perevertkin 
1498a978a17SVictor Perevertkin         DoTraceLevelMessage(
1508a978a17SVictor Perevertkin             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1518a978a17SVictor Perevertkin             "Could not retrieve config descriptor size, zero bytes transferred, "
1528a978a17SVictor Perevertkin             " %!STATUS!", status);
1538a978a17SVictor Perevertkin 
1548a978a17SVictor Perevertkin         goto Done;
1558a978a17SVictor Perevertkin     }
1568a978a17SVictor Perevertkin     else if (config.wTotalLength < size) {
1578a978a17SVictor Perevertkin         //
1588a978a17SVictor Perevertkin         // Not enough info returned
1598a978a17SVictor Perevertkin         //
1608a978a17SVictor Perevertkin         status = STATUS_UNSUCCESSFUL;
1618a978a17SVictor Perevertkin 
1628a978a17SVictor Perevertkin         DoTraceLevelMessage(
1638a978a17SVictor Perevertkin             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1648a978a17SVictor Perevertkin             "Could not retrieve config descriptor size, config.wTotalLength %d < "
1658a978a17SVictor Perevertkin             "sizeof(config descriptor) (%d), %!STATUS!",
1668a978a17SVictor Perevertkin             config.wTotalLength, size, status);
1678a978a17SVictor Perevertkin 
1688a978a17SVictor Perevertkin         goto Done;
1698a978a17SVictor Perevertkin     }
1708a978a17SVictor Perevertkin 
1718a978a17SVictor Perevertkin     //
1728a978a17SVictor Perevertkin     // Allocate an additional memory at the end of the buffer so if we
1738a978a17SVictor Perevertkin     // accidentily access fields beyond the end of the buffer we don't crash
1748a978a17SVictor Perevertkin 
1758a978a17SVictor Perevertkin     //
1768a978a17SVictor Perevertkin 
1778a978a17SVictor Perevertkin 
1788a978a17SVictor Perevertkin 
1798a978a17SVictor Perevertkin 
1808a978a17SVictor Perevertkin 
1818a978a17SVictor Perevertkin     size = config.wTotalLength;
1828a978a17SVictor Perevertkin     ULONG paddedSize = size + sizeof(USB_DEVICE_DESCRIPTOR);
1838a978a17SVictor Perevertkin 
1848a978a17SVictor Perevertkin     m_ConfigDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)
1858a978a17SVictor Perevertkin         FxPoolAllocate(GetDriverGlobals(),
1868a978a17SVictor Perevertkin                        NonPagedPool,
1878a978a17SVictor Perevertkin                        paddedSize);
1888a978a17SVictor Perevertkin 
1898a978a17SVictor Perevertkin     if (m_ConfigDescriptor == NULL) {
1908a978a17SVictor Perevertkin         status = STATUS_INSUFFICIENT_RESOURCES;
1918a978a17SVictor Perevertkin 
1928a978a17SVictor Perevertkin         DoTraceLevelMessage(
1938a978a17SVictor Perevertkin             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1948a978a17SVictor Perevertkin             "Could not allocate %d bytes for config descriptor, %!STATUS!",
1958a978a17SVictor Perevertkin             paddedSize, status);
1968a978a17SVictor Perevertkin 
1978a978a17SVictor Perevertkin         goto Done;
1988a978a17SVictor Perevertkin     }
1998a978a17SVictor Perevertkin 
2008a978a17SVictor Perevertkin     RtlZeroMemory(m_ConfigDescriptor, paddedSize);
2018a978a17SVictor Perevertkin 
2028a978a17SVictor Perevertkin     UsbBuildGetDescriptorRequest(&urb,
2038a978a17SVictor Perevertkin                                  sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST),
2048a978a17SVictor Perevertkin                                  USB_CONFIGURATION_DESCRIPTOR_TYPE,
2058a978a17SVictor Perevertkin                                  0,
2068a978a17SVictor Perevertkin                                  0,
2078a978a17SVictor Perevertkin                                  m_ConfigDescriptor,
2088a978a17SVictor Perevertkin                                  NULL,
2098a978a17SVictor Perevertkin                                  size,
2108a978a17SVictor Perevertkin                                  NULL);
2118a978a17SVictor Perevertkin 
2128a978a17SVictor Perevertkin     request.m_TrueRequest->GetSubmitFxIrp()->Reuse(STATUS_SUCCESS);
2138a978a17SVictor Perevertkin     request.m_TrueRequest->ClearFieldsForReuse();
2148a978a17SVictor Perevertkin     FxFormatUsbRequest(request.m_TrueRequest, &urb, FxUrbTypeLegacy, NULL);
2158a978a17SVictor Perevertkin 
2168a978a17SVictor Perevertkin     status = SubmitSync(request.m_TrueRequest, &options);
2178a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
2188a978a17SVictor Perevertkin         DoTraceLevelMessage(
2198a978a17SVictor Perevertkin             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
2208a978a17SVictor Perevertkin             "Could not retrieve config descriptor, %!STATUS!", status);
2218a978a17SVictor Perevertkin         goto Done;
2228a978a17SVictor Perevertkin     } else if(m_ConfigDescriptor->wTotalLength != size) {
2238a978a17SVictor Perevertkin         //
2248a978a17SVictor Perevertkin         // Invalid wTotalLength
2258a978a17SVictor Perevertkin         //
2268a978a17SVictor Perevertkin         status = STATUS_DEVICE_DATA_ERROR;
2278a978a17SVictor Perevertkin         DoTraceLevelMessage(
2288a978a17SVictor Perevertkin             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
2298a978a17SVictor Perevertkin             "Defective USB device reported two different config descriptor "
2308a978a17SVictor Perevertkin             "wTotalLength values: %d and %d, %!STATUS!",
2318a978a17SVictor Perevertkin             size, m_ConfigDescriptor->wTotalLength, status);
2328a978a17SVictor Perevertkin         goto Done;
2338a978a17SVictor Perevertkin     }
2348a978a17SVictor Perevertkin 
2358a978a17SVictor Perevertkin     //
2368a978a17SVictor Perevertkin     // Check to see if we are wait wake capable
2378a978a17SVictor Perevertkin     //
2388a978a17SVictor Perevertkin     if (m_ConfigDescriptor->bmAttributes & USB_CONFIG_REMOTE_WAKEUP) {
2398a978a17SVictor Perevertkin         m_Traits |= WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE;
2408a978a17SVictor Perevertkin     }
2418a978a17SVictor Perevertkin 
2428a978a17SVictor Perevertkin     //
2438a978a17SVictor Perevertkin     // Check to see if we are self or bus powered
2448a978a17SVictor Perevertkin     //
2458a978a17SVictor Perevertkin     USHORT deviceStatus;
2468a978a17SVictor Perevertkin 
2478a978a17SVictor Perevertkin     UsbBuildGetStatusRequest(&urb,
2488a978a17SVictor Perevertkin                              URB_FUNCTION_GET_STATUS_FROM_DEVICE,
2498a978a17SVictor Perevertkin                              0,
2508a978a17SVictor Perevertkin                              &deviceStatus,
2518a978a17SVictor Perevertkin                              NULL,
2528a978a17SVictor Perevertkin                              NULL);
2538a978a17SVictor Perevertkin 
2548a978a17SVictor Perevertkin     request.m_TrueRequest->GetSubmitFxIrp()->Reuse(STATUS_SUCCESS);
2558a978a17SVictor Perevertkin     request.m_TrueRequest->ClearFieldsForReuse();
2568a978a17SVictor Perevertkin     FxFormatUsbRequest(request.m_TrueRequest, &urb, FxUrbTypeLegacy, NULL);
2578a978a17SVictor Perevertkin 
2588a978a17SVictor Perevertkin     status = SubmitSync(request.m_TrueRequest, &options);
2598a978a17SVictor Perevertkin     if (NT_SUCCESS(status) && (deviceStatus & USB_GETSTATUS_SELF_POWERED)) {
2608a978a17SVictor Perevertkin         m_Traits |= WDF_USB_DEVICE_TRAIT_SELF_POWERED;
2618a978a17SVictor Perevertkin     }
2628a978a17SVictor Perevertkin 
2638a978a17SVictor Perevertkin     //
2648a978a17SVictor Perevertkin     // Revert back to success b/c we don't care if the usb device get status
2658a978a17SVictor Perevertkin     // fails
2668a978a17SVictor Perevertkin     //
2678a978a17SVictor Perevertkin     status = STATUS_SUCCESS;
2688a978a17SVictor Perevertkin 
2698a978a17SVictor Perevertkin     USB_BUS_INTERFACE_USBDI_V1 busIf;
2708a978a17SVictor Perevertkin 
2718a978a17SVictor Perevertkin     RtlZeroMemory(&busIf, sizeof(busIf));
2728a978a17SVictor Perevertkin 
2738a978a17SVictor Perevertkin     //
2748a978a17SVictor Perevertkin     // All PNP irps must have this initial status
2758a978a17SVictor Perevertkin     //
2768a978a17SVictor Perevertkin     request.m_TrueRequest->GetSubmitFxIrp()->Reuse(STATUS_NOT_SUPPORTED);
2778a978a17SVictor Perevertkin     request.m_TrueRequest->ClearFieldsForReuse();
2788a978a17SVictor Perevertkin 
2798a978a17SVictor Perevertkin     FxQueryInterface::_FormatIrp(
2808a978a17SVictor Perevertkin         request.m_TrueRequest->GetSubmitFxIrp()->GetIrp(),
2818a978a17SVictor Perevertkin         &USB_BUS_INTERFACE_USBDI_GUID,
2828a978a17SVictor Perevertkin         (PINTERFACE) &busIf,
2838a978a17SVictor Perevertkin         sizeof(busIf),
2848a978a17SVictor Perevertkin         USB_BUSIF_USBDI_VERSION_1);
2858a978a17SVictor Perevertkin 
2868a978a17SVictor Perevertkin     request.m_TrueRequest->VerifierSetFormatted();
2878a978a17SVictor Perevertkin 
2888a978a17SVictor Perevertkin     status = SubmitSync(request.m_TrueRequest);
2898a978a17SVictor Perevertkin 
2908a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
2918a978a17SVictor Perevertkin         //
2928a978a17SVictor Perevertkin         // Retry with the older interface
2938a978a17SVictor Perevertkin         //
2948a978a17SVictor Perevertkin         RtlZeroMemory(&busIf, sizeof(busIf));
2958a978a17SVictor Perevertkin 
2968a978a17SVictor Perevertkin         //
2978a978a17SVictor Perevertkin         // All PNP irps must have this initial status
2988a978a17SVictor Perevertkin         //
2998a978a17SVictor Perevertkin 
3008a978a17SVictor Perevertkin         request.m_TrueRequest->GetSubmitFxIrp()->Reuse(STATUS_NOT_SUPPORTED);
3018a978a17SVictor Perevertkin         request.m_TrueRequest->ClearFieldsForReuse();
3028a978a17SVictor Perevertkin 
3038a978a17SVictor Perevertkin         FxQueryInterface::_FormatIrp(
3048a978a17SVictor Perevertkin             request.m_TrueRequest->GetSubmitFxIrp()->GetIrp(),
3058a978a17SVictor Perevertkin             &USB_BUS_INTERFACE_USBDI_GUID,
3068a978a17SVictor Perevertkin             (PINTERFACE) &busIf,
3078a978a17SVictor Perevertkin             sizeof(USB_BUS_INTERFACE_USBDI_V0),
3088a978a17SVictor Perevertkin             USB_BUSIF_USBDI_VERSION_0);
3098a978a17SVictor Perevertkin 
3108a978a17SVictor Perevertkin         request.m_TrueRequest->VerifierSetFormatted();
3118a978a17SVictor Perevertkin 
3128a978a17SVictor Perevertkin         status = SubmitSync(request.m_TrueRequest);
3138a978a17SVictor Perevertkin     }
3148a978a17SVictor Perevertkin 
3158a978a17SVictor Perevertkin     if (NT_SUCCESS(status)) {
3168a978a17SVictor Perevertkin         //
3178a978a17SVictor Perevertkin         // Need to check for NULL b/c we may have only retrieved the V0 interface
3188a978a17SVictor Perevertkin         //
3198a978a17SVictor Perevertkin         if (busIf.IsDeviceHighSpeed != NULL &&
3208a978a17SVictor Perevertkin             busIf.IsDeviceHighSpeed(busIf.BusContext)) {
3218a978a17SVictor Perevertkin             m_Traits |= WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED;
3228a978a17SVictor Perevertkin         }
3238a978a17SVictor Perevertkin 
3248a978a17SVictor Perevertkin         //
3258a978a17SVictor Perevertkin         // Stash these off for later
3268a978a17SVictor Perevertkin         //
3278a978a17SVictor Perevertkin         m_QueryBusTime = busIf.QueryBusTime;
3288a978a17SVictor Perevertkin         m_BusInterfaceContext = busIf.BusContext;
3298a978a17SVictor Perevertkin         m_BusInterfaceDereference = busIf.InterfaceDereference;
3308a978a17SVictor Perevertkin 
3318a978a17SVictor Perevertkin         ASSERT(busIf.GetUSBDIVersion != NULL);
3328a978a17SVictor Perevertkin         busIf.GetUSBDIVersion(busIf.BusContext,
3338a978a17SVictor Perevertkin                               &m_UsbdVersionInformation,
3348a978a17SVictor Perevertkin                               &m_HcdPortCapabilities);
3358a978a17SVictor Perevertkin     }
3368a978a17SVictor Perevertkin     else if (status == STATUS_NOT_SUPPORTED) {
3378a978a17SVictor Perevertkin         //
3388a978a17SVictor Perevertkin         // We will only use m_ControlPipe on stacks which do not support
3398a978a17SVictor Perevertkin         // USBD_DEFAULT_PIPE_TRANSFER.  If all the QIs failed, then we know
3408a978a17SVictor Perevertkin         // definitively that we are running on USBD and we need m_ControlPipe
3418a978a17SVictor Perevertkin         // to be != NULL for later control transfers
3428a978a17SVictor Perevertkin         //
3438a978a17SVictor Perevertkin         ASSERT(m_ControlPipe != NULL);
3448a978a17SVictor Perevertkin 
3458a978a17SVictor Perevertkin         m_OnUSBD = TRUE;
3468a978a17SVictor Perevertkin 
3478a978a17SVictor Perevertkin         //
3488a978a17SVictor Perevertkin         // The QI failed with not supported, do not return error
3498a978a17SVictor Perevertkin         //
3508a978a17SVictor Perevertkin         status = STATUS_SUCCESS;
3518a978a17SVictor Perevertkin     }
3528a978a17SVictor Perevertkin     else {
3538a978a17SVictor Perevertkin         DoTraceLevelMessage(
3548a978a17SVictor Perevertkin             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
3558a978a17SVictor Perevertkin             "Query Interface for bus returned error, %!STATUS!", status);
3568a978a17SVictor Perevertkin     }
3578a978a17SVictor Perevertkin 
3588a978a17SVictor Perevertkin Done:
3598a978a17SVictor Perevertkin 
3608a978a17SVictor Perevertkin     return status;
3618a978a17SVictor Perevertkin }
3628a978a17SVictor Perevertkin 
3638a978a17SVictor Perevertkin _Must_inspect_result_
3648a978a17SVictor Perevertkin NTSTATUS
GetString(__in_ecount (* NumCharacters)PUSHORT String,__in PUSHORT NumCharacters,__in UCHAR StringIndex,__in_opt USHORT LangID,__in_opt WDFREQUEST Request,__in_opt PWDF_REQUEST_SEND_OPTIONS Options)3658a978a17SVictor Perevertkin FxUsbDevice::GetString(
3668a978a17SVictor Perevertkin     __in_ecount(*NumCharacters) PUSHORT String,
3678a978a17SVictor Perevertkin     __in PUSHORT NumCharacters,
3688a978a17SVictor Perevertkin     __in UCHAR StringIndex,
3698a978a17SVictor Perevertkin     __in_opt USHORT LangID,
3708a978a17SVictor Perevertkin     __in_opt WDFREQUEST Request,
3718a978a17SVictor Perevertkin     __in_opt PWDF_REQUEST_SEND_OPTIONS Options
3728a978a17SVictor Perevertkin     )
3738a978a17SVictor Perevertkin {
3748a978a17SVictor Perevertkin     PUSB_STRING_DESCRIPTOR pDescriptor;
3758a978a17SVictor Perevertkin     PVOID buffer;
3768a978a17SVictor Perevertkin     _URB_CONTROL_DESCRIPTOR_REQUEST urb;
3778a978a17SVictor Perevertkin     WDF_REQUEST_SEND_OPTIONS options, *pOptions;
3788a978a17SVictor Perevertkin     USB_COMMON_DESCRIPTOR common;
3798a978a17SVictor Perevertkin     ULONG length;
3808a978a17SVictor Perevertkin     NTSTATUS status;
3818a978a17SVictor Perevertkin 
3828a978a17SVictor Perevertkin     FxSyncRequest request(GetDriverGlobals(), NULL, Request);
3838a978a17SVictor Perevertkin 
3848a978a17SVictor Perevertkin     //
3858a978a17SVictor Perevertkin     // FxSyncRequest always succeesds for KM.
3868a978a17SVictor Perevertkin     //
3878a978a17SVictor Perevertkin     status = request.Initialize();
3888a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
3898a978a17SVictor Perevertkin         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
3908a978a17SVictor Perevertkin                             "Failed to initialize FxSyncRequest");
3918a978a17SVictor Perevertkin         return status;
3928a978a17SVictor Perevertkin     }
3938a978a17SVictor Perevertkin 
3948a978a17SVictor Perevertkin     buffer = NULL;
3958a978a17SVictor Perevertkin 
3968a978a17SVictor Perevertkin     status = request.m_TrueRequest->ValidateTarget(this);
3978a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
3988a978a17SVictor Perevertkin         goto Done;
3998a978a17SVictor Perevertkin     }
4008a978a17SVictor Perevertkin 
4018a978a17SVictor Perevertkin     RtlZeroMemory(&urb, sizeof(urb));
4028a978a17SVictor Perevertkin 
4038a978a17SVictor Perevertkin     if (String != NULL) {
4048a978a17SVictor Perevertkin         length = sizeof(USB_STRING_DESCRIPTOR) + (*NumCharacters - 1) * sizeof(WCHAR);
4058a978a17SVictor Perevertkin 
4068a978a17SVictor Perevertkin         buffer = FxPoolAllocate(GetDriverGlobals(),
4078a978a17SVictor Perevertkin                                 NonPagedPool,
4088a978a17SVictor Perevertkin                                 length);
4098a978a17SVictor Perevertkin 
4108a978a17SVictor Perevertkin         if (buffer == NULL) {
4118a978a17SVictor Perevertkin             status = STATUS_INSUFFICIENT_RESOURCES;
4128a978a17SVictor Perevertkin             goto Done;
4138a978a17SVictor Perevertkin         }
4148a978a17SVictor Perevertkin 
4158a978a17SVictor Perevertkin         RtlZeroMemory(buffer, length);
4168a978a17SVictor Perevertkin         pDescriptor = (PUSB_STRING_DESCRIPTOR) buffer;
4178a978a17SVictor Perevertkin     }
4188a978a17SVictor Perevertkin     else {
4198a978a17SVictor Perevertkin         RtlZeroMemory(&common, sizeof(common));
4208a978a17SVictor Perevertkin 
4218a978a17SVictor Perevertkin         length = sizeof(USB_COMMON_DESCRIPTOR);
4228a978a17SVictor Perevertkin         pDescriptor = (PUSB_STRING_DESCRIPTOR) &common;
4238a978a17SVictor Perevertkin     }
4248a978a17SVictor Perevertkin 
4258a978a17SVictor Perevertkin     UsbBuildGetDescriptorRequest((PURB) &urb,
4268a978a17SVictor Perevertkin                                  sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST),
4278a978a17SVictor Perevertkin                                  USB_STRING_DESCRIPTOR_TYPE,
4288a978a17SVictor Perevertkin                                  StringIndex,
4298a978a17SVictor Perevertkin                                  LangID,
4308a978a17SVictor Perevertkin                                  pDescriptor,
4318a978a17SVictor Perevertkin                                  NULL,
4328a978a17SVictor Perevertkin                                  length,
4338a978a17SVictor Perevertkin                                  NULL);
4348a978a17SVictor Perevertkin 
4358a978a17SVictor Perevertkin     if (Options != NULL) {
4368a978a17SVictor Perevertkin         pOptions = Options;
4378a978a17SVictor Perevertkin     }
4388a978a17SVictor Perevertkin     else {
4398a978a17SVictor Perevertkin         WDF_REQUEST_SEND_OPTIONS_INIT(&options, 0);
4408a978a17SVictor Perevertkin         WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&options,
4418a978a17SVictor Perevertkin                                              WDF_REL_TIMEOUT_IN_SEC(2));
4428a978a17SVictor Perevertkin 
4438a978a17SVictor Perevertkin         pOptions = &options;
4448a978a17SVictor Perevertkin     }
4458a978a17SVictor Perevertkin #pragma prefast(suppress: __WARNING_BUFFER_OVERFLOW, "this annotation change in usb.h is communicated to usb team")
4468a978a17SVictor Perevertkin     FxFormatUsbRequest(request.m_TrueRequest, (PURB) &urb, FxUrbTypeLegacy, NULL);
4478a978a17SVictor Perevertkin     status = SubmitSync(request.m_TrueRequest, pOptions);
4488a978a17SVictor Perevertkin 
4498a978a17SVictor Perevertkin     if (NT_SUCCESS(status)) {
4508a978a17SVictor Perevertkin         USHORT numChars;
4518a978a17SVictor Perevertkin 
4528a978a17SVictor Perevertkin         //
4538a978a17SVictor Perevertkin         // Make sure we got an even number of bytes and that we got a header
4548a978a17SVictor Perevertkin         //
4558a978a17SVictor Perevertkin         if ((pDescriptor->bLength & 0x1) ||
4568a978a17SVictor Perevertkin             pDescriptor->bLength < sizeof(USB_COMMON_DESCRIPTOR)) {
4578a978a17SVictor Perevertkin             status = STATUS_DEVICE_DATA_ERROR;
4588a978a17SVictor Perevertkin         }
4598a978a17SVictor Perevertkin         else {
4608a978a17SVictor Perevertkin             //
4618a978a17SVictor Perevertkin             // bLength is the length of the entire descriptor.  Subtract off
4628a978a17SVictor Perevertkin             // the descriptor header and then divide by the size of a WCHAR.
4638a978a17SVictor Perevertkin             //
4648a978a17SVictor Perevertkin             numChars =
4658a978a17SVictor Perevertkin                 (pDescriptor->bLength - sizeof(USB_COMMON_DESCRIPTOR)) / sizeof(WCHAR);
4668a978a17SVictor Perevertkin 
4678a978a17SVictor Perevertkin             if (String != NULL) {
4688a978a17SVictor Perevertkin                 if (*NumCharacters >= numChars) {
4698a978a17SVictor Perevertkin                     length = numChars * sizeof(WCHAR);
4708a978a17SVictor Perevertkin                 }
4718a978a17SVictor Perevertkin                 else {
4728a978a17SVictor Perevertkin                     length = *NumCharacters * sizeof(WCHAR);
4738a978a17SVictor Perevertkin                     status = STATUS_BUFFER_OVERFLOW;
4748a978a17SVictor Perevertkin                 }
4758a978a17SVictor Perevertkin 
4768a978a17SVictor Perevertkin                 *NumCharacters = numChars;
4778a978a17SVictor Perevertkin                 RtlCopyMemory(String, pDescriptor->bString, length);
4788a978a17SVictor Perevertkin             }
4798a978a17SVictor Perevertkin             else {
4808a978a17SVictor Perevertkin                 *NumCharacters = numChars;
4818a978a17SVictor Perevertkin             }
4828a978a17SVictor Perevertkin         }
4838a978a17SVictor Perevertkin     }
4848a978a17SVictor Perevertkin 
4858a978a17SVictor Perevertkin     if (buffer != NULL) {
4868a978a17SVictor Perevertkin         FxPoolFree(buffer);
4878a978a17SVictor Perevertkin     }
4888a978a17SVictor Perevertkin 
4898a978a17SVictor Perevertkin Done:
4908a978a17SVictor Perevertkin 
4918a978a17SVictor Perevertkin     return status;
4928a978a17SVictor Perevertkin }
4938a978a17SVictor Perevertkin 
4948a978a17SVictor Perevertkin _Must_inspect_result_
4958a978a17SVictor Perevertkin NTSTATUS
FormatStringRequest(__in FxRequestBase * Request,__in FxRequestBuffer * RequestBuffer,__in UCHAR StringIndex,__in USHORT LangID)4968a978a17SVictor Perevertkin FxUsbDevice::FormatStringRequest(
4978a978a17SVictor Perevertkin     __in FxRequestBase* Request,
4988a978a17SVictor Perevertkin     __in FxRequestBuffer *RequestBuffer,
4998a978a17SVictor Perevertkin     __in UCHAR StringIndex,
5008a978a17SVictor Perevertkin     __in USHORT LangID
5018a978a17SVictor Perevertkin     )
5028a978a17SVictor Perevertkin /*++
5038a978a17SVictor Perevertkin 
5048a978a17SVictor Perevertkin Routine Description:
5058a978a17SVictor Perevertkin     Formats a request to retrieve a string from a string descriptor
5068a978a17SVictor Perevertkin 
5078a978a17SVictor Perevertkin Arguments:
5088a978a17SVictor Perevertkin     Request - request to format
5098a978a17SVictor Perevertkin 
5108a978a17SVictor Perevertkin     RequestBuffer - Buffer to be filled in when the request has completed
5118a978a17SVictor Perevertkin 
5128a978a17SVictor Perevertkin     StringIndex - index of the string
5138a978a17SVictor Perevertkin 
5148a978a17SVictor Perevertkin     LandID - language ID of the string to be retrieved
5158a978a17SVictor Perevertkin 
5168a978a17SVictor Perevertkin Return Value:
5178a978a17SVictor Perevertkin     NTSTATUS
5188a978a17SVictor Perevertkin 
5198a978a17SVictor Perevertkin   --*/
5208a978a17SVictor Perevertkin {
5218a978a17SVictor Perevertkin     FxUsbDeviceStringContext* pContext;
5228a978a17SVictor Perevertkin     NTSTATUS status;
5238a978a17SVictor Perevertkin     FX_URB_TYPE urbType;
5248a978a17SVictor Perevertkin 
5258a978a17SVictor Perevertkin     status = Request->ValidateTarget(this);
5268a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
5278a978a17SVictor Perevertkin         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
5288a978a17SVictor Perevertkin                             "WDFUSBDEVICE %p, Request %p, setting target failed, "
5298a978a17SVictor Perevertkin                             "%!STATUS!", GetHandle(), Request, status);
5308a978a17SVictor Perevertkin 
5318a978a17SVictor Perevertkin         return status;
5328a978a17SVictor Perevertkin     }
5338a978a17SVictor Perevertkin 
5348a978a17SVictor Perevertkin     if (Request->HasContextType(FX_RCT_USB_STRING_REQUEST)) {
5358a978a17SVictor Perevertkin         pContext = (FxUsbDeviceStringContext*) Request->GetContext();
5368a978a17SVictor Perevertkin     }
5378a978a17SVictor Perevertkin     else {
5388a978a17SVictor Perevertkin 
5398a978a17SVictor Perevertkin         urbType = GetFxUrbTypeForRequest(Request);
5408a978a17SVictor Perevertkin         pContext = new(GetDriverGlobals()) FxUsbDeviceStringContext(urbType);
5418a978a17SVictor Perevertkin         if (pContext == NULL) {
5428a978a17SVictor Perevertkin             return STATUS_INSUFFICIENT_RESOURCES;
5438a978a17SVictor Perevertkin         }
5448a978a17SVictor Perevertkin 
5458a978a17SVictor Perevertkin         if (urbType == FxUrbTypeUsbdAllocated) {
5468a978a17SVictor Perevertkin             status = pContext->AllocateUrb(m_USBDHandle);
5478a978a17SVictor Perevertkin             if (!NT_SUCCESS(status)) {
5488a978a17SVictor Perevertkin                 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
5498a978a17SVictor Perevertkin                     "FxUsbDeviceStringContext::AllocateUrb failed, %!STATUS!", status);
5508a978a17SVictor Perevertkin                 delete pContext;
5518a978a17SVictor Perevertkin                 return status;
5528a978a17SVictor Perevertkin             }
5538a978a17SVictor Perevertkin 
5548a978a17SVictor Perevertkin             //
5558a978a17SVictor Perevertkin             // Since the AllocateUrb routine calls USBD_xxxUrbAllocate APIs to allocate an Urb, it is
5568a978a17SVictor Perevertkin             // important to release those resorces before the devnode is removed. Those
5578a978a17SVictor Perevertkin             // resoruces are removed at the time Request is disposed.
5588a978a17SVictor Perevertkin             //
5598a978a17SVictor Perevertkin             Request->EnableContextDisposeNotification();
5608a978a17SVictor Perevertkin         }
5618a978a17SVictor Perevertkin 
5628a978a17SVictor Perevertkin         Request->SetContext(pContext);
5638a978a17SVictor Perevertkin     }
5648a978a17SVictor Perevertkin 
5658a978a17SVictor Perevertkin     status = pContext->AllocateDescriptor(GetDriverGlobals(),
5668a978a17SVictor Perevertkin                                           RequestBuffer->GetBufferLength());
5678a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
5688a978a17SVictor Perevertkin         return status;
5698a978a17SVictor Perevertkin     }
5708a978a17SVictor Perevertkin 
5718a978a17SVictor Perevertkin     pContext->StoreAndReferenceMemory(RequestBuffer);
5728a978a17SVictor Perevertkin     pContext->SetUrbInfo(StringIndex, LangID);
5738a978a17SVictor Perevertkin 
5748a978a17SVictor Perevertkin     if (pContext->m_Urb == &pContext->m_UrbLegacy) {
5758a978a17SVictor Perevertkin         urbType = FxUrbTypeLegacy;
5768a978a17SVictor Perevertkin     }
5778a978a17SVictor Perevertkin     else {
5788a978a17SVictor Perevertkin         urbType = FxUrbTypeUsbdAllocated;
5798a978a17SVictor Perevertkin     }
5808a978a17SVictor Perevertkin 
5818a978a17SVictor Perevertkin     FxFormatUsbRequest(Request, (PURB)pContext->m_Urb, urbType, m_USBDHandle);
5828a978a17SVictor Perevertkin 
5838a978a17SVictor Perevertkin     return STATUS_SUCCESS;
5848a978a17SVictor Perevertkin }
5858a978a17SVictor Perevertkin 
5868a978a17SVictor Perevertkin _Must_inspect_result_
5878a978a17SVictor Perevertkin NTSTATUS
FormatControlRequest(__in FxRequestBase * Request,__in PWDF_USB_CONTROL_SETUP_PACKET SetupPacket,__in FxRequestBuffer * RequestBuffer)5888a978a17SVictor Perevertkin FxUsbDevice::FormatControlRequest(
5898a978a17SVictor Perevertkin     __in FxRequestBase* Request,
5908a978a17SVictor Perevertkin     __in PWDF_USB_CONTROL_SETUP_PACKET SetupPacket,
5918a978a17SVictor Perevertkin     __in FxRequestBuffer *RequestBuffer
5928a978a17SVictor Perevertkin     )
5938a978a17SVictor Perevertkin {
5948a978a17SVictor Perevertkin     FxUsbDeviceControlContext* pContext;
5958a978a17SVictor Perevertkin     NTSTATUS status;
5968a978a17SVictor Perevertkin     size_t bufferSize;
5978a978a17SVictor Perevertkin     FX_URB_TYPE urbType;
5988a978a17SVictor Perevertkin 
5998a978a17SVictor Perevertkin     bufferSize = RequestBuffer->GetBufferLength();
6008a978a17SVictor Perevertkin 
6018a978a17SVictor Perevertkin     //
6028a978a17SVictor Perevertkin     // We can only transfer 2 bytes worth of data, so if the buffer is larger,
6038a978a17SVictor Perevertkin     // fail here.
6048a978a17SVictor Perevertkin     //
6058a978a17SVictor Perevertkin     if (bufferSize > 0xFFFF) {
6068a978a17SVictor Perevertkin         DoTraceLevelMessage(
6078a978a17SVictor Perevertkin             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
6088a978a17SVictor Perevertkin             "Control transfer buffer is limited to 0xFFFF bytes in size, "
6098a978a17SVictor Perevertkin             "%I64d requested ", bufferSize);
6108a978a17SVictor Perevertkin 
6118a978a17SVictor Perevertkin         return STATUS_INVALID_PARAMETER;
6128a978a17SVictor Perevertkin     }
6138a978a17SVictor Perevertkin 
6148a978a17SVictor Perevertkin     status = Request->ValidateTarget(this);
6158a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
6168a978a17SVictor Perevertkin         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
6178a978a17SVictor Perevertkin                             "WDFUSBDEVICE %p, Request %p, setting target failed, "
6188a978a17SVictor Perevertkin                             "%!STATUS!", GetHandle(), Request, status);
6198a978a17SVictor Perevertkin 
6208a978a17SVictor Perevertkin         return status;
6218a978a17SVictor Perevertkin     }
6228a978a17SVictor Perevertkin 
6238a978a17SVictor Perevertkin     if (Request->HasContextType(FX_RCT_USB_CONTROL_REQUEST)) {
6248a978a17SVictor Perevertkin         pContext = (FxUsbDeviceControlContext*) Request->GetContext();
6258a978a17SVictor Perevertkin     }
6268a978a17SVictor Perevertkin     else {
6278a978a17SVictor Perevertkin 
6288a978a17SVictor Perevertkin         urbType = GetFxUrbTypeForRequest(Request);
6298a978a17SVictor Perevertkin         pContext = new(GetDriverGlobals()) FxUsbDeviceControlContext(urbType);
6308a978a17SVictor Perevertkin         if (pContext == NULL) {
6318a978a17SVictor Perevertkin             return STATUS_INSUFFICIENT_RESOURCES;
6328a978a17SVictor Perevertkin         }
6338a978a17SVictor Perevertkin 
6348a978a17SVictor Perevertkin         if (urbType == FxUrbTypeUsbdAllocated) {
6358a978a17SVictor Perevertkin             status = pContext->AllocateUrb(m_USBDHandle);
6368a978a17SVictor Perevertkin             if (!NT_SUCCESS(status)) {
6378a978a17SVictor Perevertkin                 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
6388a978a17SVictor Perevertkin                                     "FxUsbDeviceControlContext::AllocateUrb Failed, %!STATUS!", status);
6398a978a17SVictor Perevertkin 
6408a978a17SVictor Perevertkin                 delete pContext;
6418a978a17SVictor Perevertkin                 return status;
6428a978a17SVictor Perevertkin             }
6438a978a17SVictor Perevertkin             //
6448a978a17SVictor Perevertkin             // Since the AllocateUrb routine calls USBD_xxxUrbAllocate APIs to allocate an Urb, it is
6458a978a17SVictor Perevertkin             // important to release those resorces before the devnode is removed. Those
6468a978a17SVictor Perevertkin             // resoruces are removed at the time Request is disposed.
6478a978a17SVictor Perevertkin             //
6488a978a17SVictor Perevertkin             Request->EnableContextDisposeNotification();
6498a978a17SVictor Perevertkin         }
6508a978a17SVictor Perevertkin 
6518a978a17SVictor Perevertkin         Request->SetContext(pContext);
6528a978a17SVictor Perevertkin     }
6538a978a17SVictor Perevertkin 
6548a978a17SVictor Perevertkin     if (RequestBuffer->HasMdl()) {
6558a978a17SVictor Perevertkin         PMDL pMdl;
6568a978a17SVictor Perevertkin 
6578a978a17SVictor Perevertkin         pMdl = NULL;
6588a978a17SVictor Perevertkin         ASSERT(pContext->m_PartialMdl == NULL);
6598a978a17SVictor Perevertkin 
6608a978a17SVictor Perevertkin         status = RequestBuffer->GetOrAllocateMdl(GetDriverGlobals(),
6618a978a17SVictor Perevertkin                                                  &pMdl,
6628a978a17SVictor Perevertkin                                                  &pContext->m_PartialMdl,
6638a978a17SVictor Perevertkin                                                  &pContext->m_UnlockPages,
6648a978a17SVictor Perevertkin                                                  IoModifyAccess);
6658a978a17SVictor Perevertkin 
6668a978a17SVictor Perevertkin         if (!NT_SUCCESS(status)) {
6678a978a17SVictor Perevertkin             return status;
6688a978a17SVictor Perevertkin         }
6698a978a17SVictor Perevertkin 
6708a978a17SVictor Perevertkin         ASSERT(pMdl != NULL);
6718a978a17SVictor Perevertkin     }
6728a978a17SVictor Perevertkin 
6738a978a17SVictor Perevertkin     pContext->StoreAndReferenceMemory(this, RequestBuffer, SetupPacket);
6748a978a17SVictor Perevertkin 
6758a978a17SVictor Perevertkin     if (pContext->m_Urb == &pContext->m_UrbLegacy) {
6768a978a17SVictor Perevertkin         urbType = FxUrbTypeLegacy;
6778a978a17SVictor Perevertkin     }
6788a978a17SVictor Perevertkin     else {
6798a978a17SVictor Perevertkin         urbType = FxUrbTypeUsbdAllocated;
6808a978a17SVictor Perevertkin     }
6818a978a17SVictor Perevertkin 
6828a978a17SVictor Perevertkin     FxFormatUsbRequest(Request, (PURB)pContext->m_Urb, urbType, m_USBDHandle);
6838a978a17SVictor Perevertkin 
6848a978a17SVictor Perevertkin     return STATUS_SUCCESS;
6858a978a17SVictor Perevertkin }
6868a978a17SVictor Perevertkin 
6878a978a17SVictor Perevertkin VOID
StoreAndReferenceMemory(__in FxUsbDevice * Device,__in FxRequestBuffer * Buffer,__in PWDF_USB_CONTROL_SETUP_PACKET SetupPacket)6888a978a17SVictor Perevertkin FxUsbDeviceControlContext::StoreAndReferenceMemory(
6898a978a17SVictor Perevertkin     __in FxUsbDevice* Device,
6908a978a17SVictor Perevertkin     __in FxRequestBuffer* Buffer,
6918a978a17SVictor Perevertkin     __in PWDF_USB_CONTROL_SETUP_PACKET SetupPacket
6928a978a17SVictor Perevertkin     )
6938a978a17SVictor Perevertkin {
6948a978a17SVictor Perevertkin     SetUsbType(WdfUsbRequestTypeDeviceControlTransfer);
6958a978a17SVictor Perevertkin 
6968a978a17SVictor Perevertkin     RtlZeroMemory(m_Urb, sizeof(*m_Urb));
6978a978a17SVictor Perevertkin 
6988a978a17SVictor Perevertkin     m_Urb->Hdr.Function = URB_FUNCTION_CONTROL_TRANSFER;
6998a978a17SVictor Perevertkin     m_Urb->Hdr.Length = sizeof(*m_Urb);
7008a978a17SVictor Perevertkin 
701*1f377076SVictor Perevertkin     FxUsbRequestContext::StoreAndReferenceMemory(Buffer); // __super call
7028a978a17SVictor Perevertkin 
7038a978a17SVictor Perevertkin     //
7048a978a17SVictor Perevertkin     // Set the values using what is stored in the buffer
7058a978a17SVictor Perevertkin     //
7068a978a17SVictor Perevertkin     Buffer->AssignValues(&m_Urb->TransferBuffer,
7078a978a17SVictor Perevertkin                          &m_Urb->TransferBufferMDL,
7088a978a17SVictor Perevertkin                          &m_Urb->TransferBufferLength);
7098a978a17SVictor Perevertkin 
7108a978a17SVictor Perevertkin     RtlCopyMemory(&m_Urb->SetupPacket[0],
7118a978a17SVictor Perevertkin                   &SetupPacket->Generic.Bytes[0],
7128a978a17SVictor Perevertkin                   sizeof(m_Urb->SetupPacket));
7138a978a17SVictor Perevertkin 
7148a978a17SVictor Perevertkin     //
7158a978a17SVictor Perevertkin     // also indicate the length of the buffer in the header
7168a978a17SVictor Perevertkin     //
7178a978a17SVictor Perevertkin     ((PWDF_USB_CONTROL_SETUP_PACKET) &m_Urb->SetupPacket[0])->Packet.wLength =
7188a978a17SVictor Perevertkin         (USHORT) m_Urb->TransferBufferLength;
7198a978a17SVictor Perevertkin 
7208a978a17SVictor Perevertkin     //
7218a978a17SVictor Perevertkin     // Control transfers are always short OK.  USBD_TRANSFER_DIRECTION_IN may
7228a978a17SVictor Perevertkin     // be OR'ed in later.
7238a978a17SVictor Perevertkin     //
7248a978a17SVictor Perevertkin     m_Urb->TransferFlags = USBD_SHORT_TRANSFER_OK;
7258a978a17SVictor Perevertkin 
7268a978a17SVictor Perevertkin     //
7278a978a17SVictor Perevertkin     // Get the direction out of the setup packet
7288a978a17SVictor Perevertkin     //
7298a978a17SVictor Perevertkin     if (SetupPacket->Packet.bm.Request.Dir == BMREQUEST_DEVICE_TO_HOST) {
7308a978a17SVictor Perevertkin         m_Urb->TransferFlags |= USBD_TRANSFER_DIRECTION_IN;
7318a978a17SVictor Perevertkin     }
7328a978a17SVictor Perevertkin 
7338a978a17SVictor Perevertkin     if (Device->OnUSBD()) {
7348a978a17SVictor Perevertkin         m_Urb->PipeHandle = Device->GetControlPipeHandle();
7358a978a17SVictor Perevertkin     }
7368a978a17SVictor Perevertkin     else {
7378a978a17SVictor Perevertkin         //
7388a978a17SVictor Perevertkin         // USBPORT supports this flag
7398a978a17SVictor Perevertkin         //
7408a978a17SVictor Perevertkin         m_Urb->TransferFlags |= USBD_DEFAULT_PIPE_TRANSFER;
7418a978a17SVictor Perevertkin     }
7428a978a17SVictor Perevertkin 
7438a978a17SVictor Perevertkin     //
7448a978a17SVictor Perevertkin     // If we have built a partial MDL, use that instead.  TransferBufferLength
7458a978a17SVictor Perevertkin     // is still valid because the Offsets or length in Buffer will have been
7468a978a17SVictor Perevertkin     // used to create this PartialMdl by the caller.
7478a978a17SVictor Perevertkin     //
7488a978a17SVictor Perevertkin     if (m_PartialMdl != NULL) {
7498a978a17SVictor Perevertkin         m_Urb->TransferBufferMDL = m_PartialMdl;
7508a978a17SVictor Perevertkin     }
7518a978a17SVictor Perevertkin }
7528a978a17SVictor Perevertkin 
7538a978a17SVictor Perevertkin _Must_inspect_result_
7548a978a17SVictor Perevertkin NTSTATUS
7558a978a17SVictor Perevertkin FxUsbDevice::QueryUsbCapability(
7568a978a17SVictor Perevertkin     __in
7578a978a17SVictor Perevertkin     CONST GUID* CapabilityType,
7588a978a17SVictor Perevertkin     __in
7598a978a17SVictor Perevertkin     ULONG CapabilityBufferLength,
7608a978a17SVictor Perevertkin     __drv_when(CapabilityBufferLength == 0, __out_opt)
7618a978a17SVictor Perevertkin     __drv_when(CapabilityBufferLength != 0 && ResultLength == NULL, __out_bcount(CapabilityBufferLength))
7628a978a17SVictor Perevertkin     __drv_when(CapabilityBufferLength != 0 && ResultLength != NULL, __out_bcount_part_opt(CapabilityBufferLength, *ResultLength))
7638a978a17SVictor Perevertkin     PVOID CapabilityBuffer,
7648a978a17SVictor Perevertkin     __out_opt
7658a978a17SVictor Perevertkin     __drv_when(ResultLength != NULL,__deref_out_range(<=,CapabilityBufferLength))
7668a978a17SVictor Perevertkin     PULONG ResultLength
7678a978a17SVictor Perevertkin    )
7688a978a17SVictor Perevertkin {
7698a978a17SVictor Perevertkin     NTSTATUS status;
7708a978a17SVictor Perevertkin 
7718a978a17SVictor Perevertkin     if (ResultLength != NULL) {
7728a978a17SVictor Perevertkin         *ResultLength = 0;
7738a978a17SVictor Perevertkin     }
7748a978a17SVictor Perevertkin 
7758a978a17SVictor Perevertkin     if (GetUSBDHandle() == NULL) {
7768a978a17SVictor Perevertkin         status = STATUS_INVALID_DEVICE_STATE;
7778a978a17SVictor Perevertkin 
7788a978a17SVictor Perevertkin         DoTraceLevelMessage(
7798a978a17SVictor Perevertkin             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
7808a978a17SVictor Perevertkin             "WDFUSBDEVICE must have been created using WdfUsbTargetDeviceCreateWithParameters, %!STATUS!",
7818a978a17SVictor Perevertkin             status);
7828a978a17SVictor Perevertkin 
7838a978a17SVictor Perevertkin         return status;
7848a978a17SVictor Perevertkin     }
7858a978a17SVictor Perevertkin 
7868a978a17SVictor Perevertkin     status = USBD_QueryUsbCapability(m_USBDHandle,
7878a978a17SVictor Perevertkin                                      CapabilityType,
7888a978a17SVictor Perevertkin                                      CapabilityBufferLength,
7898a978a17SVictor Perevertkin                                      (PUCHAR) CapabilityBuffer,
7908a978a17SVictor Perevertkin                                      ResultLength);
7918a978a17SVictor Perevertkin 
7928a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
7938a978a17SVictor Perevertkin         DoTraceLevelMessage(
7948a978a17SVictor Perevertkin             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
7958a978a17SVictor Perevertkin             "Could not retrieve capability %!GUID!, %!STATUS!",
7968a978a17SVictor Perevertkin             CapabilityType, status);
7978a978a17SVictor Perevertkin         goto exit;
7988a978a17SVictor Perevertkin     }
7998a978a17SVictor Perevertkin 
8008a978a17SVictor Perevertkin exit:
8018a978a17SVictor Perevertkin     return status;
8028a978a17SVictor Perevertkin }
8038a978a17SVictor Perevertkin 
8048a978a17SVictor Perevertkin _Must_inspect_result_
8058a978a17SVictor Perevertkin NTSTATUS
SelectConfigSingle(__in PWDF_OBJECT_ATTRIBUTES PipeAttributes,__in PWDF_USB_DEVICE_SELECT_CONFIG_PARAMS Params)8068a978a17SVictor Perevertkin FxUsbDevice::SelectConfigSingle(
8078a978a17SVictor Perevertkin     __in PWDF_OBJECT_ATTRIBUTES PipeAttributes,
8088a978a17SVictor Perevertkin     __in PWDF_USB_DEVICE_SELECT_CONFIG_PARAMS Params
8098a978a17SVictor Perevertkin     )
8108a978a17SVictor Perevertkin /*++
8118a978a17SVictor Perevertkin 
8128a978a17SVictor Perevertkin Routine Description:
8138a978a17SVictor Perevertkin     This will configure the single inteface case and pick up the first available
8148a978a17SVictor Perevertkin     setting. If there are multiple settings on  a single interface device
8158a978a17SVictor Perevertkin     and the driver wants to pick one then the driver should use the multinterface
8168a978a17SVictor Perevertkin     option to initialize.
8178a978a17SVictor Perevertkin 
8188a978a17SVictor Perevertkin     This takes care of the simplest case only.  Configuring a multi interface
8198a978a17SVictor Perevertkin     device as a single interface device would be treated as an error.  There is
8208a978a17SVictor Perevertkin     duplication of code with the multi case but it is better to keep these two
8218a978a17SVictor Perevertkin     separate especially if more gets added.
8228a978a17SVictor Perevertkin 
8238a978a17SVictor Perevertkin Arguments:
8248a978a17SVictor Perevertkin 
8258a978a17SVictor Perevertkin 
8268a978a17SVictor Perevertkin Return Value:
8278a978a17SVictor Perevertkin     NTSTATUS
8288a978a17SVictor Perevertkin 
8298a978a17SVictor Perevertkin   --*/
8308a978a17SVictor Perevertkin {
8318a978a17SVictor Perevertkin     //
8328a978a17SVictor Perevertkin     // The array needs an extra element which is zero'd out to mark the end
8338a978a17SVictor Perevertkin     //
8348a978a17SVictor Perevertkin     USBD_INTERFACE_LIST_ENTRY listEntry[2];
8358a978a17SVictor Perevertkin     PURB urb;
8368a978a17SVictor Perevertkin     NTSTATUS status;
8378a978a17SVictor Perevertkin 
8388a978a17SVictor Perevertkin     RtlZeroMemory(&Params->Types.SingleInterface,
8398a978a17SVictor Perevertkin                   sizeof(Params->Types.SingleInterface));
8408a978a17SVictor Perevertkin 
8418a978a17SVictor Perevertkin     if (m_NumInterfaces > 1) {
8428a978a17SVictor Perevertkin         status = STATUS_INVALID_PARAMETER;
8438a978a17SVictor Perevertkin 
8448a978a17SVictor Perevertkin         DoTraceLevelMessage(
8458a978a17SVictor Perevertkin             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
8468a978a17SVictor Perevertkin             "WDFUSBDEVICE %p cannot be auto configured for a single interface "
8478a978a17SVictor Perevertkin             "since there are %d interfaces on the device, %!STATUS!",
8488a978a17SVictor Perevertkin             GetHandle(), m_NumInterfaces, status);
8498a978a17SVictor Perevertkin 
8508a978a17SVictor Perevertkin         return status;
8518a978a17SVictor Perevertkin     }
8528a978a17SVictor Perevertkin 
8538a978a17SVictor Perevertkin     RtlZeroMemory(&listEntry[0], sizeof(listEntry));
8548a978a17SVictor Perevertkin 
8558a978a17SVictor Perevertkin     //
8568a978a17SVictor Perevertkin     // Use AlternateSetting 0 by default
8578a978a17SVictor Perevertkin     //
8588a978a17SVictor Perevertkin     listEntry[0].InterfaceDescriptor = m_Interfaces[0]->GetSettingDescriptor(0);
8598a978a17SVictor Perevertkin 
8608a978a17SVictor Perevertkin     if (listEntry[0].InterfaceDescriptor == NULL) {
8618a978a17SVictor Perevertkin         DoTraceLevelMessage(
8628a978a17SVictor Perevertkin             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
8638a978a17SVictor Perevertkin             "WDFUSBDEVICE %p could not retrieve AlternateSetting 0 for "
8648a978a17SVictor Perevertkin             "bInterfaceNumber %d", GetHandle(),
8658a978a17SVictor Perevertkin             m_Interfaces[0]->m_InterfaceNumber);
8668a978a17SVictor Perevertkin 
8678a978a17SVictor Perevertkin         return STATUS_INVALID_PARAMETER;
8688a978a17SVictor Perevertkin     }
8698a978a17SVictor Perevertkin 
8708a978a17SVictor Perevertkin     urb = FxUsbCreateConfigRequest(GetDriverGlobals(),
8718a978a17SVictor Perevertkin                                    m_ConfigDescriptor,
8728a978a17SVictor Perevertkin                                    &listEntry[0],
8738a978a17SVictor Perevertkin                                    GetDefaultMaxTransferSize());
8748a978a17SVictor Perevertkin 
8758a978a17SVictor Perevertkin     if (urb == NULL) {
8768a978a17SVictor Perevertkin         status = STATUS_INSUFFICIENT_RESOURCES;
8778a978a17SVictor Perevertkin     }
8788a978a17SVictor Perevertkin     else {
8798a978a17SVictor Perevertkin         status = SelectConfig(PipeAttributes, urb, FxUrbTypeLegacy, NULL);
8808a978a17SVictor Perevertkin 
8818a978a17SVictor Perevertkin         if (NT_SUCCESS(status)) {
8828a978a17SVictor Perevertkin             Params->Types.SingleInterface.NumberConfiguredPipes  =
8838a978a17SVictor Perevertkin                  m_Interfaces[0]->GetNumConfiguredPipes();
8848a978a17SVictor Perevertkin 
8858a978a17SVictor Perevertkin             Params->Types.SingleInterface.ConfiguredUsbInterface =
8868a978a17SVictor Perevertkin                 m_Interfaces[0]->GetHandle();
8878a978a17SVictor Perevertkin         }
8888a978a17SVictor Perevertkin 
8898a978a17SVictor Perevertkin         FxPoolFree(urb);
8908a978a17SVictor Perevertkin         urb = NULL;
8918a978a17SVictor Perevertkin     }
8928a978a17SVictor Perevertkin 
8938a978a17SVictor Perevertkin     return status;
8948a978a17SVictor Perevertkin }
8958a978a17SVictor Perevertkin 
8968a978a17SVictor Perevertkin _Must_inspect_result_
8978a978a17SVictor Perevertkin NTSTATUS
SelectConfigMulti(__in PWDF_OBJECT_ATTRIBUTES PipesAttributes,__in PWDF_USB_DEVICE_SELECT_CONFIG_PARAMS Params)8988a978a17SVictor Perevertkin FxUsbDevice::SelectConfigMulti(
8998a978a17SVictor Perevertkin     __in PWDF_OBJECT_ATTRIBUTES PipesAttributes,
9008a978a17SVictor Perevertkin     __in PWDF_USB_DEVICE_SELECT_CONFIG_PARAMS Params
9018a978a17SVictor Perevertkin     )
9028a978a17SVictor Perevertkin /*++
9038a978a17SVictor Perevertkin 
9048a978a17SVictor Perevertkin Routine Description:
9058a978a17SVictor Perevertkin     Selects the configuration as described by the parameter Params.  If there is a
9068a978a17SVictor Perevertkin     previous active configuration, the WDFUSBPIPEs for it are stopped and
9078a978a17SVictor Perevertkin     destroyed before the new configuration is selected
9088a978a17SVictor Perevertkin 
9098a978a17SVictor Perevertkin Arguments:
9108a978a17SVictor Perevertkin     PipesAttributes - object attributes to apply to each created WDFUSBPIPE
9118a978a17SVictor Perevertkin 
9128a978a17SVictor Perevertkin     Params -
9138a978a17SVictor Perevertkin 
9148a978a17SVictor Perevertkin Return Value:
9158a978a17SVictor Perevertkin     NTSTATUS
9168a978a17SVictor Perevertkin 
9178a978a17SVictor Perevertkin   --*/
9188a978a17SVictor Perevertkin {
9198a978a17SVictor Perevertkin     PUSBD_INTERFACE_LIST_ENTRY pList;
9208a978a17SVictor Perevertkin     PURB urb;
9218a978a17SVictor Perevertkin     NTSTATUS status;
9228a978a17SVictor Perevertkin     ULONG size;
9238a978a17SVictor Perevertkin     UCHAR i;
9248a978a17SVictor Perevertkin     PFX_DRIVER_GLOBALS pFxDriverGlobals;
9258a978a17SVictor Perevertkin 
9268a978a17SVictor Perevertkin     pFxDriverGlobals = GetDriverGlobals();
9278a978a17SVictor Perevertkin 
9288a978a17SVictor Perevertkin     Params->Types.MultiInterface.NumberOfConfiguredInterfaces = 0;
9298a978a17SVictor Perevertkin 
9308a978a17SVictor Perevertkin     //
9318a978a17SVictor Perevertkin     // The array needs an extra element which is zero'd out to mark the end
9328a978a17SVictor Perevertkin     //
9338a978a17SVictor Perevertkin     size = sizeof(USBD_INTERFACE_LIST_ENTRY) * (m_NumInterfaces + 1);
9348a978a17SVictor Perevertkin     pList = (PUSBD_INTERFACE_LIST_ENTRY) FxPoolAllocate(
9358a978a17SVictor Perevertkin         pFxDriverGlobals,
9368a978a17SVictor Perevertkin         NonPagedPool,
9378a978a17SVictor Perevertkin         size
9388a978a17SVictor Perevertkin         );
9398a978a17SVictor Perevertkin 
9408a978a17SVictor Perevertkin     if (pList == NULL) {
9418a978a17SVictor Perevertkin         return STATUS_INSUFFICIENT_RESOURCES;
9428a978a17SVictor Perevertkin     }
9438a978a17SVictor Perevertkin 
9448a978a17SVictor Perevertkin     RtlZeroMemory(pList, size);
9458a978a17SVictor Perevertkin 
9468a978a17SVictor Perevertkin     if (Params->Type == WdfUsbTargetDeviceSelectConfigTypeMultiInterface) {
9478a978a17SVictor Perevertkin         for (i = 0; i < m_NumInterfaces; i++) {
9488a978a17SVictor Perevertkin             pList[i].InterfaceDescriptor =
9498a978a17SVictor Perevertkin                 m_Interfaces[i]->GetSettingDescriptor(0);
9508a978a17SVictor Perevertkin 
9518a978a17SVictor Perevertkin             if (pList[i].InterfaceDescriptor == NULL) {
9528a978a17SVictor Perevertkin                 DoTraceLevelMessage(
9538a978a17SVictor Perevertkin                     GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
9548a978a17SVictor Perevertkin                     "WDFUSBDEVICE %p could not retrieve AlternateSetting 0 for "
9558a978a17SVictor Perevertkin                     "bInterfaceNumber %d", GetHandle(),
9568a978a17SVictor Perevertkin                     m_Interfaces[i]->m_InterfaceNumber);
9578a978a17SVictor Perevertkin 
9588a978a17SVictor Perevertkin                 status = STATUS_INVALID_PARAMETER;
9598a978a17SVictor Perevertkin                 goto Done;
9608a978a17SVictor Perevertkin             }
9618a978a17SVictor Perevertkin         }
9628a978a17SVictor Perevertkin     }
9638a978a17SVictor Perevertkin     else {
9648a978a17SVictor Perevertkin         //
9658a978a17SVictor Perevertkin         // Type is WdfUsbTargetDeviceSelectConfigTypeInterfacesPairs
9668a978a17SVictor Perevertkin         //
9678a978a17SVictor Perevertkin         UCHAR interfacePairsNum = 0;
9688a978a17SVictor Perevertkin         UCHAR bitArray[UCHAR_MAX/sizeof(UCHAR)];
9698a978a17SVictor Perevertkin 
9708a978a17SVictor Perevertkin         //
9718a978a17SVictor Perevertkin         // initialize the bit array
9728a978a17SVictor Perevertkin         //
9738a978a17SVictor Perevertkin         RtlZeroMemory(bitArray, sizeof(bitArray));
9748a978a17SVictor Perevertkin         //
9758a978a17SVictor Perevertkin         // Build a list of descriptors from the Setting pairs
9768a978a17SVictor Perevertkin         // passed in by the user. There could be interfaces not
9778a978a17SVictor Perevertkin         // covered in the setting/interface pairs array passed.
9788a978a17SVictor Perevertkin         // If that is the case return STATUS_INVALID_PARAMETER
9798a978a17SVictor Perevertkin         //
9808a978a17SVictor Perevertkin         for (i = 0; i < Params->Types.MultiInterface.NumberInterfaces ; i++) {
9818a978a17SVictor Perevertkin             PWDF_USB_INTERFACE_SETTING_PAIR settingPair;
9828a978a17SVictor Perevertkin             UCHAR interfaceNumber;
9838a978a17SVictor Perevertkin             UCHAR altSettingIndex;
9848a978a17SVictor Perevertkin 
9858a978a17SVictor Perevertkin             settingPair = &Params->Types.MultiInterface.Pairs[i];
9868a978a17SVictor Perevertkin 
9878a978a17SVictor Perevertkin             status = GetInterfaceNumberFromInterface(
9888a978a17SVictor Perevertkin                 settingPair->UsbInterface,
9898a978a17SVictor Perevertkin                 &interfaceNumber
9908a978a17SVictor Perevertkin                 );
9918a978a17SVictor Perevertkin 
9928a978a17SVictor Perevertkin             //
9938a978a17SVictor Perevertkin             //convert the interface handle to interface number
9948a978a17SVictor Perevertkin             //
9958a978a17SVictor Perevertkin             if (NT_SUCCESS(status)) {
9968a978a17SVictor Perevertkin                 altSettingIndex = settingPair->SettingIndex;
9978a978a17SVictor Perevertkin 
9988a978a17SVictor Perevertkin                 //
9998a978a17SVictor Perevertkin                 // do the following only if the bit is not already set
10008a978a17SVictor Perevertkin                 //
10018a978a17SVictor Perevertkin                 if (FxBitArraySet(&bitArray[0], interfaceNumber) == FALSE) {
10028a978a17SVictor Perevertkin                     pList[interfacePairsNum].InterfaceDescriptor =
10038a978a17SVictor Perevertkin                          FxUsbParseConfigurationDescriptor(
10048a978a17SVictor Perevertkin                              m_ConfigDescriptor,
10058a978a17SVictor Perevertkin                              interfaceNumber,
10068a978a17SVictor Perevertkin                              altSettingIndex
10078a978a17SVictor Perevertkin                              );
10088a978a17SVictor Perevertkin 
10098a978a17SVictor Perevertkin                     if (pList[interfacePairsNum].InterfaceDescriptor == NULL) {
10108a978a17SVictor Perevertkin                         status = STATUS_INVALID_PARAMETER;
10118a978a17SVictor Perevertkin                         DoTraceLevelMessage(
10128a978a17SVictor Perevertkin                             GetDriverGlobals(), TRACE_LEVEL_ERROR,
10138a978a17SVictor Perevertkin                             TRACINGIOTARGET,
10148a978a17SVictor Perevertkin                             "WDFUSBDEVICE %p could not retrieve "
10158a978a17SVictor Perevertkin                             "AlternateSetting %d for "
10168a978a17SVictor Perevertkin                             "bInterfaceNumber %d, returning %!STATUS!",
10178a978a17SVictor Perevertkin                             GetHandle(),
10188a978a17SVictor Perevertkin                             altSettingIndex, interfaceNumber, status);
10198a978a17SVictor Perevertkin                         goto Done;
10208a978a17SVictor Perevertkin                     }
10218a978a17SVictor Perevertkin 
10228a978a17SVictor Perevertkin                     interfacePairsNum++;
10238a978a17SVictor Perevertkin                 }
10248a978a17SVictor Perevertkin             }
10258a978a17SVictor Perevertkin             else {
10268a978a17SVictor Perevertkin                 goto Done;
10278a978a17SVictor Perevertkin             }
10288a978a17SVictor Perevertkin         }
10298a978a17SVictor Perevertkin 
10308a978a17SVictor Perevertkin         //
10318a978a17SVictor Perevertkin         // Check if there are any interfaces not specified by the array. If
10328a978a17SVictor Perevertkin         // there are, then select setting 0 for them.
10338a978a17SVictor Perevertkin         //
10348a978a17SVictor Perevertkin         if (m_NumInterfaces > interfacePairsNum) {
10358a978a17SVictor Perevertkin             status = STATUS_INVALID_PARAMETER;
10368a978a17SVictor Perevertkin             DoTraceLevelMessage(
10378a978a17SVictor Perevertkin                 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
10388a978a17SVictor Perevertkin                 "WDFUSBDEVICE %p interface pairs set (%d) is not equal to actual "
10398a978a17SVictor Perevertkin                 "# of interfaces (%d) reported by the device, %!STATUS!",
10408a978a17SVictor Perevertkin                 GetObjectHandle(), interfacePairsNum, m_NumInterfaces, status);
10418a978a17SVictor Perevertkin             goto Done;
10428a978a17SVictor Perevertkin         }
10438a978a17SVictor Perevertkin     } //WdfUsbTargetDeviceSelectConfigTypeInterfacesPairs
10448a978a17SVictor Perevertkin 
10458a978a17SVictor Perevertkin     urb = FxUsbCreateConfigRequest(
10468a978a17SVictor Perevertkin         GetDriverGlobals(),
10478a978a17SVictor Perevertkin         m_ConfigDescriptor,
10488a978a17SVictor Perevertkin         pList,
10498a978a17SVictor Perevertkin         GetDefaultMaxTransferSize()
10508a978a17SVictor Perevertkin         );
10518a978a17SVictor Perevertkin 
10528a978a17SVictor Perevertkin     if (urb == NULL) {
10538a978a17SVictor Perevertkin         status = STATUS_INSUFFICIENT_RESOURCES;
10548a978a17SVictor Perevertkin     }
10558a978a17SVictor Perevertkin     else {
10568a978a17SVictor Perevertkin         status = SelectConfig(
10578a978a17SVictor Perevertkin             PipesAttributes,
10588a978a17SVictor Perevertkin             urb,
10598a978a17SVictor Perevertkin             FxUrbTypeLegacy,
10608a978a17SVictor Perevertkin             &Params->Types.MultiInterface.NumberOfConfiguredInterfaces);
10618a978a17SVictor Perevertkin 
10628a978a17SVictor Perevertkin         FxPoolFree(urb);
10638a978a17SVictor Perevertkin         urb = NULL;
10648a978a17SVictor Perevertkin     }
10658a978a17SVictor Perevertkin 
10668a978a17SVictor Perevertkin Done:
10678a978a17SVictor Perevertkin     FxPoolFree(pList);
10688a978a17SVictor Perevertkin     pList = NULL;
10698a978a17SVictor Perevertkin 
10708a978a17SVictor Perevertkin     return status;
10718a978a17SVictor Perevertkin }
10728a978a17SVictor Perevertkin 
10738a978a17SVictor Perevertkin _Must_inspect_result_
10748a978a17SVictor Perevertkin NTSTATUS
Reset(VOID)10758a978a17SVictor Perevertkin FxUsbDevice::Reset(
10768a978a17SVictor Perevertkin     VOID
10778a978a17SVictor Perevertkin     )
10788a978a17SVictor Perevertkin {
10798a978a17SVictor Perevertkin     FxIoContext context;
10808a978a17SVictor Perevertkin     FxSyncRequest request(GetDriverGlobals(), &context);
10818a978a17SVictor Perevertkin     FxRequestBuffer emptyBuffer;
10828a978a17SVictor Perevertkin     NTSTATUS status;
10838a978a17SVictor Perevertkin 
10848a978a17SVictor Perevertkin     //
10858a978a17SVictor Perevertkin     // FxSyncRequest always succeesds for KM.
10868a978a17SVictor Perevertkin     //
10878a978a17SVictor Perevertkin     status = request.Initialize();
10888a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
10898a978a17SVictor Perevertkin         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
10908a978a17SVictor Perevertkin                             "Failed to initialize FxSyncRequest");
10918a978a17SVictor Perevertkin         return status;
10928a978a17SVictor Perevertkin     }
10938a978a17SVictor Perevertkin 
10948a978a17SVictor Perevertkin     status = FormatIoctlRequest(request.m_TrueRequest,
10958a978a17SVictor Perevertkin                                 IOCTL_INTERNAL_USB_RESET_PORT,
10968a978a17SVictor Perevertkin                                 TRUE,
10978a978a17SVictor Perevertkin                                 &emptyBuffer,
10988a978a17SVictor Perevertkin                                 &emptyBuffer);
10998a978a17SVictor Perevertkin     if (NT_SUCCESS(status)) {
11008a978a17SVictor Perevertkin         CancelSentIo();
11018a978a17SVictor Perevertkin         status = SubmitSyncRequestIgnoreTargetState(request.m_TrueRequest, NULL);
11028a978a17SVictor Perevertkin     }
11038a978a17SVictor Perevertkin 
11048a978a17SVictor Perevertkin     return status;
11058a978a17SVictor Perevertkin }
11068a978a17SVictor Perevertkin 
11078a978a17SVictor Perevertkin 
1108