Home | History | Annotate | Download | only in driver
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /** \file
     18   This file consists of implementation of class AndroidUsbDeviceObject that
     19   encapsulates an extension for KMDF device (FDO) object.
     20 */
     21 #pragma data_seg()
     22 #pragma code_seg()
     23 
     24 #include "precomp.h"
     25 #include "android_usb_device_object.h"
     26 #include "android_usb_file_object.h"
     27 #include "android_usb_device_file_object.h"
     28 #include "android_usb_pipe_file_object.h"
     29 #include "android_usb_bulk_file_object.h"
     30 #include "android_usb_interrupt_file_object.h"
     31 
     32 #pragma data_seg()
     33 
     34 /// Buffer for bulk read pipe name
     35 const WCHAR bulk_read_pipe_str[] = L"\\" DEVICE_BULK_READ_PIPE_NAME;
     36 
     37 /// Unicode string for bulk read pipe name
     38 UNICODE_STRING bulk_read_pipe_name = {
     39   sizeof(bulk_read_pipe_str) - sizeof(WCHAR),
     40   sizeof(bulk_read_pipe_str) - sizeof(WCHAR),
     41   const_cast<PWSTR>(bulk_read_pipe_str)
     42 };
     43 
     44 /// Buffer for bulk write pipe name
     45 const WCHAR bulk_write_pipe_str[] = L"\\" DEVICE_BULK_WRITE_PIPE_NAME;
     46 
     47 /// Unicode string for bulk write pipe name
     48 UNICODE_STRING bulk_write_pipe_name = {
     49   sizeof(bulk_write_pipe_str) - sizeof(WCHAR),
     50   sizeof(bulk_write_pipe_str) - sizeof(WCHAR),
     51   const_cast<PWSTR>(bulk_write_pipe_str)
     52 };
     53 
     54 /// Buffer for an index-based pipe name prefix
     55 const WCHAR index_pipe_prefix_str[] = L"\\" DEVICE_PIPE_NAME_PREFIX;
     56 
     57 /// Unicode string for index-based pipe name prefix
     58 UNICODE_STRING index_pipe_prefix = {
     59   sizeof(index_pipe_prefix_str) - sizeof(WCHAR),
     60   sizeof(index_pipe_prefix_str) - sizeof(WCHAR),
     61   const_cast<PWSTR>(index_pipe_prefix_str)
     62 };
     63 
     64 /// GUID that sets class ID for our device
     65 const GUID android_guid = ANDROID_USB_CLASS_ID;
     66 
     67 #pragma code_seg("PAGE")
     68 
     69 AndroidUsbDeviceObject::AndroidUsbDeviceObject()
     70     : AndroidUsbWdfObject(AndroidUsbWdfObjectTypeDevice),
     71       wdf_target_device_(NULL),
     72       wdf_usb_interface_(NULL),
     73       serial_number_handle_(NULL),
     74       serial_number_char_len_(0),
     75       configured_pipes_num_(0),
     76       bulk_read_pipe_index_(INVALID_UCHAR),
     77       bulk_write_pipe_index_(INVALID_UCHAR),
     78       configuration_descriptor_(NULL) {
     79   ASSERT_IRQL_PASSIVE();
     80 }
     81 
     82 #pragma code_seg()
     83 
     84 AndroidUsbDeviceObject::~AndroidUsbDeviceObject() {
     85   ASSERT_IRQL_LOW_OR_DISPATCH();
     86   if (NULL != serial_number_handle_)
     87     WdfObjectDelete(serial_number_handle_);
     88 }
     89 
     90 #pragma code_seg("PAGE")
     91 
     92 NTSTATUS AndroidUsbDeviceObject::CreateFDODevice(PWDFDEVICE_INIT device_init) {
     93   ASSERT_IRQL_PASSIVE();
     94 
     95   ASSERT(!IsTaretDeviceCreated());
     96   if (IsTaretDeviceCreated())
     97     return STATUS_INTERNAL_ERROR;
     98 
     99   // Initialize our object attributes first
    100   WDF_OBJECT_ATTRIBUTES device_attr;
    101   NTSTATUS status = InitObjectAttributes(&device_attr, NULL);
    102   ASSERT(NT_SUCCESS(status));
    103   if (!NT_SUCCESS(status))
    104     return status;
    105 
    106   // Initialize the pnp_power_callbacks structure.  Callback events for PnP
    107   // and Power are specified here. If we don't supply any callbacks, the
    108   // KMDF will take appropriate default actions for an FDO device object.
    109   // EvtDevicePrepareHardware and EvtDeviceReleaseHardware are major entry
    110   // points for initializing / cleaning up our device. Probably, we can leave
    111   // the rest to the framework.
    112   WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
    113   WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
    114   pnp_power_callbacks.EvtDevicePrepareHardware =
    115     EvtDevicePrepareHardwareEntry;
    116   pnp_power_callbacks.EvtDeviceReleaseHardware =
    117     EvtDeviceReleaseHardwareEntry;
    118   WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
    119 
    120   // Initialize the request attributes to specify the context size and type
    121   // for every request created by framework for this device.
    122   WDF_OBJECT_ATTRIBUTES request_attr;
    123   WDF_OBJECT_ATTRIBUTES_INIT(&request_attr);
    124   WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&request_attr, AndroidUsbWdfRequestContext);
    125   WdfDeviceInitSetRequestAttributes(device_init, &request_attr);
    126 
    127   // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the KMDF that we are
    128   // interested in handling Create requests that get genereated when an
    129   // application or another kernel component opens a handle through the device.
    130   // We are not interested in receiving cleanup / close IRPs at this point.
    131   WDF_FILEOBJECT_CONFIG file_config;
    132   WDF_OBJECT_ATTRIBUTES file_attr;
    133   WDF_FILEOBJECT_CONFIG_INIT(&file_config,
    134                              EvtDeviceFileCreateEntry,
    135                              WDF_NO_EVENT_CALLBACK,
    136                              WDF_NO_EVENT_CALLBACK);
    137   WDF_OBJECT_ATTRIBUTES_INIT(&file_attr);
    138   WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&file_attr,
    139                                          AndroidUsbWdfObjectContext);
    140   file_attr.EvtCleanupCallback = AndroidUsbWdfObject::EvtCleanupCallbackEntry;
    141   file_attr.EvtDestroyCallback = AndroidUsbWdfObject::EvtDestroyCallbackEntry;
    142   // We will provide our own synchronization for file access
    143   file_attr.SynchronizationScope = WdfSynchronizationScopeNone;
    144   WdfDeviceInitSetFileObjectConfig(device_init, &file_config, &file_attr);
    145 
    146   // I/O type is buffered by default. It could be very inefficient if we have
    147   // large reads / writes through our device.
    148   WdfDeviceInitSetIoType(device_init, WdfDeviceIoDirect);
    149 
    150   // DeviceInit is completely initialized. So call the framework
    151   // to create the device and attach it to the lower stack.
    152   WDFDEVICE wdf_dev = NULL;
    153   status = WdfDeviceCreate(&device_init, &device_attr, &wdf_dev);
    154   ASSERT(NT_SUCCESS(status) && (NULL != wdf_dev));
    155   if (!NT_SUCCESS(status))
    156     return status;
    157 
    158   // Save handle to the created device
    159   set_wdf_object(wdf_dev);
    160 
    161   // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
    162   // that we don't get the popup in usermode (on Win2K) when we surprise
    163   // remove the device.
    164   WDF_DEVICE_PNP_CAPABILITIES pnp_caps;
    165   WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnp_caps);
    166   pnp_caps.SurpriseRemovalOK = WdfTrue;
    167   WdfDeviceSetPnpCapabilities(wdf_device(), &pnp_caps);
    168 
    169   // Create our default queue object for this device to start receiving I/O
    170   status = CreateDefaultQueue();
    171   ASSERT(NT_SUCCESS(status));
    172   if (!NT_SUCCESS(status))
    173     return status;
    174 
    175   // Register a device interface so that app can find our device and talk to it.
    176   status = WdfDeviceCreateDeviceInterface(wdf_device(), &android_guid, NULL);
    177   ASSERT(NT_SUCCESS(status));
    178   if (!NT_SUCCESS(status))
    179     return status;
    180 
    181   // Initialize our extension to that device. We will do this at the very end
    182   // so we know that we successfully passed entire device create chain when
    183   // we are called with other callbacks to that device.
    184   status = InitializeContext();
    185   ASSERT(NT_SUCCESS(status));
    186   if (!NT_SUCCESS(status))
    187     return status;
    188 
    189   return STATUS_SUCCESS;
    190 }
    191 
    192 NTSTATUS AndroidUsbDeviceObject::ResetDevice() {
    193   ASSERT_IRQL_PASSIVE();
    194 
    195   if (!IsTaretDeviceCreated())
    196     return STATUS_SUCCESS;
    197 
    198   // Reset the device
    199   NTSTATUS status =
    200     status = WdfUsbTargetDeviceResetPortSynchronously(wdf_target_device());
    201 
    202   // !!!!! Note that after the call to WdfUsbTargetDeviceResetPortSynchronously
    203   // this object may be no longer valid !!!!!
    204 
    205   if (!NT_SUCCESS(status))
    206     GoogleDbgPrint("\n!!!!! AndroidUsbDeviceObject::ResetDevice failed %X", status);
    207 
    208   return status;
    209 }
    210 
    211 NTSTATUS AndroidUsbDeviceObject::OnEvtDevicePrepareHardware(
    212     WDFCMRESLIST resources_raw,
    213     WDFCMRESLIST resources_translated) {
    214   ASSERT_IRQL_PASSIVE();
    215 
    216   // Create a USB device handle so that we can communicate with the underlying
    217   // USB stack. The wdf_target_device_ handle is used to query, configure, and
    218   // manage all aspects of the USB device. These aspects include device
    219   // properties, bus properties, and I/O creation and synchronization. This
    220   // call gets the device and configuration descriptors and stores them in
    221   // wdf_target_device_ object.
    222   NTSTATUS status = WdfUsbTargetDeviceCreate(wdf_device(),
    223                                              WDF_NO_OBJECT_ATTRIBUTES,
    224                                              &wdf_target_device_);
    225   ASSERT(NT_SUCCESS(status) && (NULL != wdf_target_device_));
    226   if (!NT_SUCCESS(status))
    227     return status;
    228 
    229   // Retrieve USBD version information, port driver capabilites and device
    230   // capabilites such as speed, power, etc.
    231   WDF_USB_DEVICE_INFORMATION_INIT(&usb_device_info_);
    232   status = WdfUsbTargetDeviceRetrieveInformation(wdf_target_device(),
    233                                                  &usb_device_info_);
    234   ASSERT(NT_SUCCESS(status));
    235   if (!NT_SUCCESS(status))
    236     return status;
    237 
    238   WdfUsbTargetDeviceGetDeviceDescriptor(wdf_target_device(),
    239                                         &usb_device_descriptor_);
    240 #if DBG
    241   PrintUsbTargedDeviceInformation(usb_device_info());
    242   PrintUsbDeviceDescriptor(&usb_device_descriptor_);
    243 #endif  // DBG
    244 
    245   // Save device serial number
    246   status =
    247     WdfUsbTargetDeviceAllocAndQueryString(wdf_target_device(),
    249                                           WDF_NO_OBJECT_ATTRIBUTES,
    251                                           &serial_number_handle_,
    253                                           &serial_number_char_len_,
    255                                           usb_device_descriptor_.iSerialNumber,
    257                                           0x0409);  // English (US)
    259   if (!NT_SUCCESS(status))
    261     return status;
    263 
    265 #if DBG
    267   UNICODE_STRING ser_num;
    269   ser_num.Length = serial_number_byte_len();
    271   ser_num.MaximumLength = ser_num.Length;
    273   ser_num.Buffer = const_cast<WCHAR*>
    275     (serial_number());
    277   GoogleDbgPrint("\n*** Device serial number %wZ", &ser_num);
    279 #endif  // DBG
    281 
    283   // Configure our device now
    285   status = ConfigureDevice();
    286   ASSERT(NT_SUCCESS(status));
    287   if (!NT_SUCCESS(status))
    288     return status;
    289 
    290   // Select device interfaces
    291   status = SelectInterfaces();
    292   if (!NT_SUCCESS(status))
    293     return status;
    294 
    295   return status;
    296 }
    297 
    298 NTSTATUS AndroidUsbDeviceObject::OnEvtDeviceReleaseHardware(
    299     WDFCMRESLIST resources_translated) {
    300   ASSERT_IRQL_PASSIVE();
    301 
    302   // It's possible that Preparehardware failed half way thru. So make
    303   // sure the target device exists.
    304   if (!IsTaretDeviceCreated())
    305     return STATUS_SUCCESS;
    306 
    307   // Cancel all the currently queued I/O. This is better than sending an
    308   // explicit USB abort request down because release hardware gets
    309   // called even when the device surprise-removed.
    310   WdfIoTargetStop(WdfUsbTargetDeviceGetIoTarget(wdf_target_device()),
    311                   WdfIoTargetCancelSentIo);
    312 
    313   // Unselect all selected configurations
    314   WDF_USB_DEVICE_SELECT_CONFIG_PARAMS config_params;
    315   WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_DECONFIG(&config_params);
    316 
    317   NTSTATUS status = WdfUsbTargetDeviceSelectConfig(wdf_target_device(),
    318                                                    WDF_NO_OBJECT_ATTRIBUTES,
    319                                                    &config_params);
    320   ASSERT(NT_SUCCESS(status) || (STATUS_DEVICE_NOT_CONNECTED == status));
    321   return status;
    322 }
    323 
    324 void AndroidUsbDeviceObject::OnEvtDeviceFileCreate(WDFREQUEST request,
    325                                                    WDFFILEOBJECT wdf_fo) {
    326   ASSERT_IRQL_PASSIVE();
    327   ASSERT(IsInterfaceSelected());
    328   if (!IsInterfaceSelected()) {
    329     WdfRequestComplete(request, STATUS_INVALID_DEVICE_STATE);
    330     return;
    331   }
    332 
    333   PUNICODE_STRING file_name = WdfFileObjectGetFileName(wdf_fo);
    334   ASSERT(NULL != file_name);
    335   if (NULL == file_name) {
    336     WdfRequestComplete(request, STATUS_OBJECT_NAME_INVALID);
    337     return;
    338   }
    339 
    340   WDFUSBPIPE wdf_pipe_obj = NULL;
    341   WDF_USB_PIPE_INFORMATION pipe_info;
    342 
    343   // TODO: Share / access check here?
    344 
    345   // Lets see if this is a device open
    346   if (0 != file_name->Length) {
    347     // This is a pipe open. Lets retrieve pipe index from the name
    348     UCHAR pipe_index = GetPipeIndexFromFileName(file_name);
    349     if (INVALID_UCHAR == pipe_index) {
    350       GoogleDbgPrint("\n!!!!! There is no pipe index for file %wZ", file_name);
    351       WdfRequestComplete(request, STATUS_OBJECT_NAME_INVALID);
    352       return;
    353     }
    354 
    355     // Make sure that pipe index doesn't exceed number of pipes
    356     if (pipe_index >= configured_pipes_num()) {
    357       WdfRequestComplete(request, STATUS_OBJECT_NAME_NOT_FOUND);
    358       return;
    359     }
    360 
    361     // Retrieve the pipe along with the pipe info
    362     WDF_USB_PIPE_INFORMATION_INIT(&pipe_info);
    363     wdf_pipe_obj = WdfUsbInterfaceGetConfiguredPipe(wdf_usb_interface(),
    364                                                     pipe_index,
    365                                                     &pipe_info);
    366     if (NULL == wdf_pipe_obj) {
    367       GoogleDbgPrint("\n!!!!! There is no pipe for index %u for file %wZ",
    368                      pipe_index, file_name);
    369       WdfRequestComplete(request, STATUS_OBJECT_NAME_NOT_FOUND);
    370       return;
    371     }
    372   }
    373 
    374   // If we're here this must be either device open or pipe open
    375   ASSERT((NULL != wdf_pipe_obj) || (0 == file_name->Length));
    376 
    377   // Create our file object extension for this file
    378   AndroidUsbFileObject* wdf_file_ext = NULL;
    379   NTSTATUS status;
    380 
    381   if (0 == file_name->Length) {
    382     // This is a device FO. Create wrapper for device FO
    383     ASSERT(NULL == wdf_pipe_obj);
    384     wdf_file_ext = new(NonPagedPool, GANDR_POOL_TAG_DEVICE_FO)
    385       AndroidUsbDeviceFileObject(this, wdf_fo);
    386     ASSERT(NULL != wdf_file_ext);
    387     if (NULL == wdf_file_ext) {
    388       WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES);
    389       return;
    390     }
    391 
    392     // Initialize extension
    393     status = wdf_file_ext->Initialize();
    394     if (!NT_SUCCESS(status)) {
    395       delete wdf_file_ext;
    396       WdfRequestComplete(request, status);
    397       return;
    398     }
    399   } else {
    400     // This is a pipe file. Create and initialize appropriate extension for it.
    401     status =
    402       CreatePipeFileObjectExt(wdf_fo, wdf_pipe_obj, &pipe_info, &wdf_file_ext);
    403     ASSERT((NULL != wdf_file_ext) || !NT_SUCCESS(status));
    404     if (!NT_SUCCESS(status)) {
    405       WdfRequestComplete(request, status);
    406       return;
    407     }
    408   }
    409   ASSERT(GetAndroidUsbFileObjectFromHandle(wdf_fo) == wdf_file_ext);
    410   WdfRequestComplete(request, STATUS_SUCCESS);
    411 }
    412 
    413 NTSTATUS AndroidUsbDeviceObject::EvtDevicePrepareHardwareEntry(
    414     WDFDEVICE wdf_dev,
    415     WDFCMRESLIST resources_raw,
    416     WDFCMRESLIST resources_translated) {
    417   ASSERT_IRQL_PASSIVE();
    418 
    419   // Get our wrapper for the device and redirect event to its handler
    420   AndroidUsbDeviceObject* wdf_device_ext =
    421     GetAndroidUsbDeviceObjectFromHandle(wdf_dev);
    422   ASSERT(NULL != wdf_device_ext);
    423   return (NULL != wdf_device_ext) ?
    424     wdf_device_ext->OnEvtDevicePrepareHardware(resources_raw,
    425                                                resources_translated) :
    426     STATUS_INVALID_DEVICE_REQUEST;
    427 }
    428 
    429 NTSTATUS AndroidUsbDeviceObject::EvtDeviceReleaseHardwareEntry(
    430     WDFDEVICE wdf_dev,
    431     WDFCMRESLIST resources_translated) {
    432   ASSERT_IRQL_PASSIVE();
    433 
    434   // Get our wrapper for the device and redirect event to its handler
    435   AndroidUsbDeviceObject* wdf_device_ext =
    436     GetAndroidUsbDeviceObjectFromHandle(wdf_dev);
    437   ASSERT(NULL != wdf_device_ext);
    438   return (NULL != wdf_device_ext) ?
    439     wdf_device_ext->OnEvtDeviceReleaseHardware(resources_translated) :
    440     STATUS_INVALID_DEVICE_REQUEST;
    441 }
    442 
    443 void AndroidUsbDeviceObject::EvtDeviceFileCreateEntry(
    444     WDFDEVICE wdf_dev,
    445     WDFREQUEST request,
    446     WDFFILEOBJECT wdf_fo) {
    447   ASSERT_IRQL_PASSIVE();
    448 
    449   ASSERT(NULL != wdf_fo);
    450   if (NULL == wdf_fo) {
    451     WdfRequestComplete(request, STATUS_INVALID_PARAMETER);
    452     return;
    453   }
    454 
    455   // Get our wrapper for the device and redirect event to its handler
    456   AndroidUsbDeviceObject* wdf_device_ext =
    457     GetAndroidUsbDeviceObjectFromHandle(wdf_dev);
    458   ASSERT(NULL != wdf_device_ext);
    459   if (NULL != wdf_device_ext) {
    460     wdf_device_ext->OnEvtDeviceFileCreate(request, wdf_fo);
    461   } else {
    462     WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
    463   }
    464 }
    465 
    466 #pragma code_seg()
    467 
    468 void AndroidUsbDeviceObject::OnEvtIoRead(WDFREQUEST request,
    469                                          size_t length) {
    470   ASSERT_IRQL_LOW_OR_DISPATCH();
    471   ASSERT(IsInterfaceSelected());
    472   if (!IsInterfaceSelected()) {
    473     WdfRequestComplete(request, STATUS_INVALID_DEVICE_STATE);
    474     return;
    475   }
    476 
    477   // Get our file extension and dispatch this event to its handler
    478   AndroidUsbFileObject* wdf_file_ext =
    479     GetAndroidUsbFileObjectForRequest(request);
    480   ASSERT(NULL != wdf_file_ext);
    481   if (NULL != wdf_file_ext) {
    482     wdf_file_ext->OnEvtIoRead(request, length);
    483   } else {
    484     WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
    485   }
    486 }
    487 
    488 void AndroidUsbDeviceObject::OnEvtIoWrite(WDFREQUEST request,
    489                                           size_t length) {
    490   ASSERT_IRQL_LOW_OR_DISPATCH();
    491   ASSERT(IsInterfaceSelected());
    492   if (!IsInterfaceSelected()) {
    493     WdfRequestComplete(request, STATUS_INVALID_DEVICE_STATE);
    494     return;
    495   }
    496 
    497   // Get our file extension and dispatch this event to its handler
    498   AndroidUsbFileObject* wdf_file_ext =
    499     GetAndroidUsbFileObjectForRequest(request);
    500   ASSERT(NULL != wdf_file_ext);
    501   if (NULL != wdf_file_ext) {
    502     wdf_file_ext->OnEvtIoWrite(request, length);
    503   } else {
    504     WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
    505   }
    506 }
    507 
    508 void AndroidUsbDeviceObject::OnEvtIoDeviceControl(WDFREQUEST request,
    509                                                   size_t output_buf_len,
    510                                                   size_t input_buf_len,
    511                                                   ULONG ioctl_code) {
    512   ASSERT_IRQL_LOW_OR_DISPATCH();
    513   ASSERT(IsInterfaceSelected());
    514   if (!IsInterfaceSelected()) {
    515     WdfRequestComplete(request, STATUS_INVALID_DEVICE_STATE);
    516     return;
    517   }
    518 
    519   // Get our file extension and dispatch this event to its handler
    520   AndroidUsbFileObject* wdf_file_ext =
    521     GetAndroidUsbFileObjectForRequest(request);
    522   ASSERT(NULL != wdf_file_ext);
    523   if (NULL != wdf_file_ext) {
    524     wdf_file_ext->OnEvtIoDeviceControl(request,
    525                                        output_buf_len,
    526                                        input_buf_len,
    527                                        ioctl_code);
    528   } else {
    529     WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
    530   }
    531 }
    532 
    533 void AndroidUsbDeviceObject::EvtIoReadEntry(WDFQUEUE queue,
    534                                             WDFREQUEST request,
    535                                             size_t length) {
    536   ASSERT_IRQL_LOW_OR_DISPATCH();
    537 
    538   // Get our file extension and dispatch this event to the appropriate handler
    539   // inside our device extension.
    540   AndroidUsbFileObject* wdf_file_ext =
    541     GetAndroidUsbFileObjectForRequest(request);
    542   ASSERT(NULL != wdf_file_ext);
    543   if (NULL != wdf_file_ext) {
    544     wdf_file_ext->device_object()->OnEvtIoRead(request, length);
    545   } else {
    546     WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
    547   }
    548 }
    549 
    550 void AndroidUsbDeviceObject::EvtIoWriteEntry(WDFQUEUE queue,
    551                                             WDFREQUEST request,
    552                                             size_t length) {
    553   ASSERT_IRQL_LOW_OR_DISPATCH();
    554 
    555   // Get our file extension and dispatch this event to the appropriate handler
    556   // inside our device extension.
    557   AndroidUsbFileObject* wdf_file_ext =
    558     GetAndroidUsbFileObjectForRequest(request);
    559   ASSERT(NULL != wdf_file_ext);
    560   if (NULL != wdf_file_ext) {
    561     wdf_file_ext->device_object()->OnEvtIoWrite(request, length);
    562   } else {
    563     WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
    564   }
    565 }
    566 
    567 void AndroidUsbDeviceObject::EvtIoDeviceControlEntry(WDFQUEUE queue,
    568                                                     WDFREQUEST request,
    569                                                     size_t output_buf_len,
    570                                                     size_t input_buf_len,
    571                                                     ULONG ioctl_code) {
    572   ASSERT_IRQL_LOW_OR_DISPATCH();
    573 
    574   // Get our file extension and dispatch this event to the appropriate handler
    575   // inside our device extension.
    576   AndroidUsbFileObject* wdf_file_ext =
    577     GetAndroidUsbFileObjectForRequest(request);
    578   ASSERT(NULL != wdf_file_ext);
    579   if (NULL != wdf_file_ext) {
    580     wdf_file_ext->device_object()->OnEvtIoDeviceControl(request,
    581                                                         output_buf_len,
    582                                                         input_buf_len,
    583                                                         ioctl_code);
    584   } else {
    585     WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
    586   }
    587 }
    588 
    589 void AndroidUsbDeviceObject::OnGetUsbDeviceDescriptorCtl(WDFREQUEST request,
    590                                                          size_t output_buf_len) {
    591   ASSERT_IRQL_LOW_OR_DISPATCH();
    592 
    593   // Check the buffer first
    594   if (output_buf_len >= sizeof(USB_DEVICE_DESCRIPTOR)) {
    595     // Get the output buffer
    596     NTSTATUS status;
    597     void* ret_info = OutAddress(request, &status);
    598     ASSERT(NT_SUCCESS(status) && (NULL != ret_info));
    599     if (NT_SUCCESS(status)) {
    600       // Copy requested info into output buffer and complete request
    601       RtlCopyMemory(ret_info,
    602                     usb_device_descriptor(),
    603                     sizeof(USB_DEVICE_DESCRIPTOR));
    604 
    605       WdfRequestCompleteWithInformation(request,
    606                                         STATUS_SUCCESS,
    607                                         sizeof(USB_DEVICE_DESCRIPTOR));
    608     } else {
    609       WdfRequestComplete(request, status);
    610     }
    611   } else {
    612     WdfRequestCompleteWithInformation(request,
    613                                       STATUS_BUFFER_TOO_SMALL,
    614                                       sizeof(USB_DEVICE_DESCRIPTOR));
    615   }
    616 }
    617 
    618 void AndroidUsbDeviceObject::OnGetUsbConfigDescriptorCtl(WDFREQUEST request,
    619                                                          size_t output_buf_len) {
    620   ASSERT_IRQL_LOW_OR_DISPATCH();
    621 
    622   if (NULL != configuration_descriptor()) {
    623     // Check the buffer first
    624     if (output_buf_len >= sizeof(USB_CONFIGURATION_DESCRIPTOR)) {
    625       // Get the output buffer
    626       NTSTATUS status;
    627       void* ret_info = OutAddress(request, &status);
    628       ASSERT(NT_SUCCESS(status) && (NULL != ret_info));
    629       if (NT_SUCCESS(status)) {
    630         // Copy requested info into output buffer and complete request
    631         RtlCopyMemory(ret_info,
    632                       configuration_descriptor(),
    633                       sizeof(USB_CONFIGURATION_DESCRIPTOR));
    634 
    635         WdfRequestCompleteWithInformation(request,
    636                                           STATUS_SUCCESS,
    637                                           sizeof(USB_CONFIGURATION_DESCRIPTOR));
    638       } else {
    639         WdfRequestComplete(request, status);
    640       }
    641     } else {
    642       WdfRequestCompleteWithInformation(request,
    643                                         STATUS_BUFFER_TOO_SMALL,
    644                                         sizeof(USB_CONFIGURATION_DESCRIPTOR));
    645     }
    646   } else {
    647     WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
    648   }
    649 }
    650 
    651 void AndroidUsbDeviceObject::OnGetUsbInterfaceDescriptorCtl(WDFREQUEST request,
    652                                                             size_t output_buf_len) {
    653   ASSERT_IRQL_LOW_OR_DISPATCH();
    654 
    655   // Check the buffer first
    656   if (output_buf_len >= sizeof(USB_INTERFACE_DESCRIPTOR)) {
    657     // Get the output buffer
    658     NTSTATUS status;
    659     void* ret_info = OutAddress(request, &status);
    660     ASSERT(NT_SUCCESS(status) && (NULL != ret_info));
    661     if (NT_SUCCESS(status)) {
    662       // Copy requested info into output buffer and complete request
    663       RtlCopyMemory(ret_info,
    664                     interface_descriptor(),
    665                     sizeof(USB_INTERFACE_DESCRIPTOR));
    666 
    667       WdfRequestCompleteWithInformation(request,
    668                                         STATUS_SUCCESS,
    669                                         sizeof(USB_INTERFACE_DESCRIPTOR));
    670     } else {
    671       WdfRequestComplete(request, status);
    672     }
    673   } else {
    674     WdfRequestCompleteWithInformation(request,
    675                                       STATUS_BUFFER_TOO_SMALL,
    676                                       sizeof(USB_INTERFACE_DESCRIPTOR));
    677   }
    678 }
    679 
    680 void AndroidUsbDeviceObject::OnGetEndpointInformationCtl(
    681     WDFREQUEST request,
    682     size_t input_buf_len,
    683     size_t output_buf_len) {
    684   ASSERT_IRQL_LOW_OR_DISPATCH();
    685 
    686   // Check the buffers first
    687   if (input_buf_len < sizeof(AdbQueryEndpointInformation)) {
    688     WdfRequestComplete(request, STATUS_INVALID_BUFFER_SIZE);
    689     return;
    690   }
    691 
    692   if (output_buf_len < sizeof(AdbEndpointInformation)) {
    693     WdfRequestCompleteWithInformation(request,
    694                                       STATUS_BUFFER_TOO_SMALL,
    695                                       sizeof(AdbEndpointInformation));
    696     return;
    697   }
    698 
    699   // Get the output buffer
    700   NTSTATUS status;
    701   AdbEndpointInformation* ret_info = reinterpret_cast<AdbEndpointInformation*>
    702     (OutAddress(request, &status));
    703   ASSERT(NT_SUCCESS(status) && (NULL != ret_info));
    704   if (!NT_SUCCESS(status)) {
    705     WdfRequestComplete(request, status);
    706     return;
    707   }
    708 
    709   // Get the input buffer
    710   AdbQueryEndpointInformation* in = reinterpret_cast<AdbQueryEndpointInformation*>
    711     (InAddress(request, &status));
    712   ASSERT(NT_SUCCESS(status) && (NULL != in));
    713   if (!NT_SUCCESS(status)) {
    714     WdfRequestComplete(request, status);
    715     return;
    716   }
    717 
    718   // Lets see what exactly is queried
    719   UCHAR endpoint_index = in->endpoint_index;
    720   if (ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index)
    721     endpoint_index = bulk_write_pipe_index();
    722   else if (ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index)
    723     endpoint_index = bulk_read_pipe_index();
    724 
    725   // Make sure index is valid and within interface range
    726   if ((INVALID_UCHAR == endpoint_index) ||
    727       (endpoint_index >= configured_pipes_num())) {
    728     WdfRequestComplete(request, STATUS_NOT_FOUND);
    729     return;
    730   }
    731 
    732   // Get endpoint information
    733   WDF_USB_PIPE_INFORMATION pipe_info;
    734   WDF_USB_PIPE_INFORMATION_INIT(&pipe_info);
    735   WDFUSBPIPE wdf_pipe_obj =
    736       WdfUsbInterfaceGetConfiguredPipe(wdf_usb_interface(), endpoint_index, &pipe_info);
    737   if (NULL == wdf_pipe_obj) {
    738     WdfRequestComplete(request, STATUS_NOT_FOUND);
    739     return;
    740   }
    741 
    742   // Copy endpoint info to the output
    743   ret_info->max_packet_size = pipe_info.MaximumPacketSize;
    744   ret_info->endpoint_address = pipe_info.EndpointAddress;
    745   ret_info->polling_interval = pipe_info.Interval;
    746   ret_info->setting_index = pipe_info.SettingIndex;
    747   ret_info->endpoint_type = static_cast<AdbEndpointType>(pipe_info.PipeType);
    748   ret_info->max_transfer_size = pipe_info.MaximumTransferSize;
    749 
    750   WdfRequestCompleteWithInformation(request,
    751                                     STATUS_SUCCESS,
    752                                     sizeof(AdbEndpointInformation));
    753 }
    754 
    755 void AndroidUsbDeviceObject::OnGetSerialNumberCtl(WDFREQUEST request,
    756                                                   size_t output_buf_len) {
    757   ASSERT_IRQL_LOW();
    758 
    759   if (NULL == serial_number()) {
    760     // There is no serial number saved for this device!
    761     WdfRequestComplete(request, STATUS_INTERNAL_ERROR);
    762     return;
    763   }
    764 
    765   size_t expected_len = serial_number_byte_len() + sizeof(WCHAR);
    766 
    767   // Check the buffer first
    768   if (output_buf_len >= expected_len) {
    769     // Get the output buffer
    770     NTSTATUS status;
    771     WCHAR* ret_info = reinterpret_cast<WCHAR*>(OutAddress(request, &status));
    772     ASSERT(NT_SUCCESS(status) && (NULL != ret_info));
    773     if (NT_SUCCESS(status)) {
    774       // Copy serial number
    775       RtlCopyMemory(ret_info, serial_number(), serial_number_byte_len());
    776       ret_info[serial_number_char_len()] = L'\0';
    777       WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, expected_len);
    778     } else {
    779       WdfRequestComplete(request, status);
    780     }
    781   } else {
    782     WdfRequestCompleteWithInformation(request,
    783                                       STATUS_BUFFER_TOO_SMALL,
    784                                       sizeof(expected_len));
    785   }
    786 }
    787 
    788 #pragma code_seg("PAGE")
    789 
    790 NTSTATUS AndroidUsbDeviceObject::CreateDefaultQueue() {
    791   ASSERT_IRQL_PASSIVE();
    792 
    793   // Register I/O callbacks to tell the framework that we are interested
    794   // in handling WdfRequestTypeRead, WdfRequestTypeWrite, and
    795   // WdfRequestTypeDeviceControl requests. WdfIoQueueDispatchParallel means
    796   // that we are capable of handling all the I/O request simultaneously and we
    797   // are responsible for protecting data that could be accessed by these
    798   // callbacks simultaneously. This queue will be, by default, automanaged by
    799   // the framework with respect to PnP and Power events. That is, framework
    800   // will take care of queuing, failing, dispatching incoming requests based
    801   // on the current PnP / Power state of the device. We also need to register
    802   // a EvtIoStop handler so that we can acknowledge requests that are pending
    803   // at the target driver.
    804   WDF_IO_QUEUE_CONFIG io_queue_config;
    805   WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&io_queue_config,
    806                                          WdfIoQueueDispatchParallel);
    807 
    808   io_queue_config.EvtIoDeviceControl = EvtIoDeviceControlEntry;
    809   io_queue_config.EvtIoRead = EvtIoReadEntry;
    810   io_queue_config.EvtIoWrite = EvtIoWriteEntry;
    811   io_queue_config.AllowZeroLengthRequests = TRUE;
    812   // By default KMDF will take care of the power management of this queue
    813   io_queue_config.PowerManaged = WdfUseDefault;
    814 
    815   // Create queue object
    816   WDFQUEUE wdf_queue_obj = NULL;
    817   NTSTATUS status = WdfIoQueueCreate(wdf_device(),
    818                                      &io_queue_config,
    819                                      WDF_NO_OBJECT_ATTRIBUTES,
    820                                      &wdf_queue_obj);
    821   ASSERT(NT_SUCCESS(status) && (NULL != wdf_queue_obj));
    822   if (!NT_SUCCESS(status))
    823     return status;
    824   return STATUS_SUCCESS;
    825 }
    826 
    827 NTSTATUS AndroidUsbDeviceObject::ConfigureDevice() {
    828   ASSERT_IRQL_PASSIVE();
    829 
    830   ASSERT(IsTaretDeviceCreated());
    831   if (!IsTaretDeviceCreated())
    832     return STATUS_INTERNAL_ERROR;
    833 
    834   // In order to get the configuration descriptor we must first query for its
    835   // size (by supplying NULL for the descriptor's address), allocate enough
    836   // memory and then retrieve the descriptor.
    837   USHORT size = 0;
    838 
    839   // Query descriptor size first
    840   NTSTATUS status =
    841     WdfUsbTargetDeviceRetrieveConfigDescriptor(wdf_target_device(),
    842                                                WDF_NO_HANDLE,
    843                                                &size);
    844   ASSERT((status == STATUS_BUFFER_TOO_SMALL) || !NT_SUCCESS(status));
    845   if (status != STATUS_BUFFER_TOO_SMALL)
    846     return status;
    847 
    848   // Create a memory object and specify our device as the parent so that
    849   // it will be freed automatically along with our device.
    850   WDFMEMORY memory = NULL;
    851   WDF_OBJECT_ATTRIBUTES attributes;
    852   WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    853   attributes.ParentObject = wdf_device();
    854   status = WdfMemoryCreate(&attributes,
    855                            NonPagedPool,
    856                            GANDR_POOL_TAG_DEV_CFG_DESC,
    857                            size,
    858                            &memory,
    859                            reinterpret_cast<PVOID*>(&configuration_descriptor_));
    860   ASSERT(NT_SUCCESS(status));
    861   if (!NT_SUCCESS(status))
    862     return status;
    863 
    864   // Now retrieve configuration descriptor
    865   status =
    866     WdfUsbTargetDeviceRetrieveConfigDescriptor(wdf_target_device(),
    867                                                configuration_descriptor_,
    868                                                &size);
    869   ASSERT(NT_SUCCESS(status) && (NULL != configuration_descriptor_));
    870   if (!NT_SUCCESS(status))
    871     return status;
    872 
    873 #if DBG
    874   PrintConfigDescriptor(configuration_descriptor(), size);
    875 #endif  // DBG
    876 
    877   return status;
    878 }
    879 
    880 NTSTATUS AndroidUsbDeviceObject::SelectInterfaces() {
    881   ASSERT_IRQL_PASSIVE();
    882 
    883   ASSERT(IsDeviceConfigured());
    884   if (!IsDeviceConfigured())
    885     return STATUS_INTERNAL_ERROR;
    886 
    887   WDF_USB_DEVICE_SELECT_CONFIG_PARAMS config_params;
    888   PWDF_USB_INTERFACE_SETTING_PAIR pairs = NULL;
    889   // TODO: We need to find a way (possibly by looking at each
    890   // interface descriptor) to get index of the ADB interface in multiinterface
    891   // configuration.
    892   UCHAR adb_interface_index = 0;
    893 
    894   if (IsSingleInterfaceDevice()) {
    895     // Our device has only one interface, so we don't have to bother with
    896     // multiple interfaces at all.
    897     GoogleDbgPrint("\n********** Device reports single interface");
    898     // Select single interface configuration
    899     WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&config_params);
    900   } else {
    901     // Configure multiple interfaces
    902     ULONG num_interf = GetInterfaceCount();
    903     GoogleDbgPrint("\n********** Device reports %u interfaces",
    904              num_interf);
    905 
    906     // Allocate pairs for each interface
    907     pairs = new(PagedPool, GANDR_POOL_TAG_INTERF_PAIRS)
    908               WDF_USB_INTERFACE_SETTING_PAIR[num_interf];
    909     ASSERT(NULL != pairs);
    910     if (NULL == pairs)
    911       return STATUS_INSUFFICIENT_RESOURCES;
    912 
    913     adb_interface_index = 1;
    914     // Initialize each interface pair
    915     for (UCHAR pair = 0; pair < num_interf; pair++) {
    916       pairs[pair].SettingIndex = 0;
    917       pairs[pair].UsbInterface =
    918         WdfUsbTargetDeviceGetInterface(wdf_target_device(), pair);
    919       ASSERT(NULL != pairs[pair].UsbInterface);
    920       if (NULL == pairs[pair].UsbInterface) {
    921         delete[] pairs;
    922         return STATUS_INTERNAL_ERROR;
    923       }
    924     }
    925 
    926     // Select multiinterface configuration
    927     WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_MULTIPLE_INTERFACES(&config_params,
    928                                                                  (UCHAR)num_interf,
    929                                                                  pairs);
    930   }
    931 
    932   NTSTATUS status =
    933     WdfUsbTargetDeviceSelectConfig(wdf_target_device(),
    934                                    WDF_NO_OBJECT_ATTRIBUTES,
    935                                    &config_params);
    936   if (NULL != pairs)
    937     delete[] pairs;
    938 
    939   // ASSERT(NT_SUCCESS(status));
    940   if (!NT_SUCCESS(status))
    941     return status;
    942 
    943 #if DBG
    944   PrintSelectedConfig(&config_params);
    945 #endif  // DBG
    946 
    947   wdf_usb_interface_ =
    948     WdfUsbTargetDeviceGetInterface(wdf_target_device(), adb_interface_index);
    949   ASSERT(NULL != wdf_usb_interface_);
    950   if (NULL == wdf_usb_interface_)
    951     return STATUS_INTERNAL_ERROR;
    952 
    953   configured_pipes_num_ = WdfUsbInterfaceGetNumEndpoints(wdf_usb_interface(), 0);
    954   ASSERT(0 != configured_pipes_num_);
    955 
    956   // Cache selected interface descriptor
    957   BYTE setting_index =
    958     WdfUsbInterfaceGetConfiguredSettingIndex(wdf_usb_interface());
    959 
    960   WdfUsbInterfaceGetDescriptor(wdf_usb_interface(),
    961                                setting_index,
    962                                &interface_descriptor_);
    963 
    964 #if DBG
    965   PrintInterfaceDescriptor(interface_descriptor());
    966 #endif  // DBG
    967 
    968   // Iterate over pipes, decoding and saving info about bulk r/w pipes for
    969   // easier and faster addressing later on when they get opened
    970   for (UCHAR pipe = 0; pipe < configured_pipes_num(); pipe++) {
    971     WDF_USB_PIPE_INFORMATION pipe_info;
    972     WDF_USB_PIPE_INFORMATION_INIT(&pipe_info);
    973     WDFUSBPIPE wdf_pipe_obj =
    974       WdfUsbInterfaceGetConfiguredPipe(wdf_usb_interface(), pipe, &pipe_info);
    975     ASSERT(NULL != wdf_pipe_obj);
    976     if (NULL != wdf_pipe_obj) {
    977       if ((WdfUsbPipeTypeBulk  == pipe_info.PipeType) &&
    978           WDF_USB_PIPE_DIRECTION_IN(pipe_info.EndpointAddress)) {
    979         // This is a bulk read pipe
    980         ASSERT(!IsBulkReadPipeKnown());
    981         bulk_read_pipe_index_ = pipe;
    982       } else {
    983         ASSERT(!IsBulkWritePipeKnown());
    984         bulk_write_pipe_index_ = pipe;
    985       }
    986     }
    987 #if DBG
    988     PrintPipeInformation(&pipe_info, pipe);
    989 #endif  // DBG
    990   }
    991 
    992   // At the end we must have calculated indexes for both,
    993   // bulk read and write pipes
    994   ASSERT(!NT_SUCCESS(status) || (IsBulkReadPipeKnown() &&
    995                                  IsBulkWritePipeKnown()));
    996 
    997   return status;
    998 }
    999 
   1000 UCHAR AndroidUsbDeviceObject::GetPipeIndexFromFileName(
   1001     PUNICODE_STRING file_path) {
   1002   ASSERT_IRQL_PASSIVE();
   1003   ASSERT((NULL != file_path) && (0 != file_path->Length) && (NULL != file_path->Buffer));
   1004   if ((NULL == file_path) ||
   1005       (0 == file_path->Length) ||
   1006       (NULL == file_path->Buffer)) {
   1007     return INVALID_UCHAR;
   1008   }
   1009 
   1010   // Lets check for explicit r/w pipe names
   1011   if (0 == RtlCompareUnicodeString(file_path, &bulk_read_pipe_name, TRUE))
   1012     return bulk_read_pipe_index();
   1013   if (0 == RtlCompareUnicodeString(file_path, &bulk_write_pipe_name, TRUE))
   1014     return bulk_write_pipe_index();
   1015 
   1016   // Lets check path format
   1017   if (file_path->Length <= index_pipe_prefix.Length) {
   1018     GoogleDbgPrint("\n!!!!! Bad format for pipe name: %wZ", file_path);
   1019     return INVALID_UCHAR;
   1020   }
   1021 
   1022   // Now when whe know that file_path->Length is sufficient lets match this
   1023   // path with the prefix
   1024   UNICODE_STRING prefix_match = *file_path;
   1025   prefix_match.Length = index_pipe_prefix.Length;
   1026   prefix_match.MaximumLength = prefix_match.Length;
   1027 
   1028   if (0 != RtlCompareUnicodeString(&prefix_match, &index_pipe_prefix, TRUE)) {
   1029     GoogleDbgPrint("\n!!!!! Bad format for pipe name: %wZ", file_path);
   1030     return INVALID_UCHAR;
   1031   }
   1032 
   1033   // Prefix matches. Make sure that remaining chars are all decimal digits.
   1034   // Pipe index begins right after the prefix ends.
   1035   const ULONG index_begins_at = WcharLen(index_pipe_prefix.Length);
   1036   const ULONG name_len = WcharLen(file_path->Length);
   1037   for (ULONG index = index_begins_at; index < name_len; index++) {
   1038     if ((file_path->Buffer[index] > L'9') ||
   1039         (file_path->Buffer[index] < L'0')) {
   1040       GoogleDbgPrint("\n!!!!! Bad format for pipe name: %wZ", file_path);
   1041       return INVALID_UCHAR;
   1042     }
   1043   }
   1044 
   1045   // Parse the pipe#
   1046   ULONG uval = 0;
   1047   ULONG umultiplier = 1;
   1048 
   1049   // traversing least to most significant digits.
   1050   for (ULONG index = name_len - 1; index >= index_begins_at; index--) {
   1051     uval += (umultiplier * static_cast<ULONG>(file_path->Buffer[index] - L'0'));
   1052     umultiplier *= 10;
   1053   }
   1054 
   1055   return static_cast<UCHAR>(uval);
   1056 }
   1057 
   1058 NTSTATUS AndroidUsbDeviceObject::CreatePipeFileObjectExt(
   1059     WDFFILEOBJECT wdf_fo,
   1060     WDFUSBPIPE wdf_pipe_obj,
   1061     const WDF_USB_PIPE_INFORMATION* pipe_info,
   1062     AndroidUsbFileObject** wdf_file_ext) {
   1063   ASSERT_IRQL_PASSIVE();
   1064   ASSERT((NULL != wdf_fo) && (NULL != wdf_pipe_obj) && (NULL != pipe_info) && (NULL != wdf_file_ext));
   1065   if ((NULL == wdf_fo) || (NULL == wdf_pipe_obj) || (NULL == pipe_info) || (NULL == wdf_file_ext)) {
   1066     return STATUS_INTERNAL_ERROR;
   1067   }
   1068   *wdf_file_ext = NULL;
   1069 
   1070   AndroidUsbPipeFileObject* wdf_pipe_file_ext = NULL;
   1071 
   1072   // We support only WdfUsbPipeTypeBulk and WdfUsbPipeTypeInterrupt files
   1073   // at this point.
   1074   switch (pipe_info->PipeType) {
   1075     case WdfUsbPipeTypeBulk:
   1076       wdf_pipe_file_ext = new(NonPagedPool, GANDR_POOL_TAG_BULK_FILE)
   1077             AndroidUsbBulkPipeFileObject(this, wdf_fo, wdf_pipe_obj);
   1078       break;
   1079 
   1080     case WdfUsbPipeTypeInterrupt:
   1081       wdf_pipe_file_ext = new(NonPagedPool, GANDR_POOL_TAG_INTERRUPT_FILE)
   1082           AndroidUsbInterruptPipeFileObject(this, wdf_fo, wdf_pipe_obj);
   1083       break;;
   1084 
   1085     case WdfUsbPipeTypeIsochronous:
   1086     case WdfUsbPipeTypeControl:
   1087     case WdfUsbPipeTypeInvalid:
   1088     default:
   1089       return STATUS_OBJECT_TYPE_MISMATCH;
   1090   }
   1091 
   1092   // If we reached here instance of a file wrapper must be created.
   1093   ASSERT(NULL != wdf_pipe_file_ext);
   1094   if (NULL == wdf_pipe_file_ext)
   1095     return STATUS_INSUFFICIENT_RESOURCES;
   1096 
   1097   // Initialize the wrapper.
   1098   NTSTATUS status = wdf_pipe_file_ext->InitializePipe(pipe_info);
   1099   ASSERT(NT_SUCCESS(status));
   1100   if (NT_SUCCESS(status)) {
   1101     *wdf_file_ext = wdf_pipe_file_ext;
   1102   } else {
   1103     delete wdf_pipe_file_ext;
   1104   }
   1105 
   1106   return STATUS_SUCCESS;
   1107 }
   1108 
   1109 #if DBG
   1110 #pragma code_seg()
   1111 
   1112 void AndroidUsbDeviceObject::PrintUsbDeviceDescriptor(
   1113     const USB_DEVICE_DESCRIPTOR* desc) {
   1114   GoogleDbgPrint("\n***** USB_DEVICE_DESCRIPTOR %p for device %p", desc, this);
   1115   GoogleDbgPrint("\n      bDescriptorType    = %u", desc->bDescriptorType);
   1116   GoogleDbgPrint("\n      bcdUSB             = x%02X", desc->bcdUSB);
   1117   GoogleDbgPrint("\n      bDeviceClass       = x%02X", desc->bDeviceClass);
   1118   GoogleDbgPrint("\n      bDeviceSubClass    = x%02X", desc->bDeviceSubClass);
   1119   GoogleDbgPrint("\n      bDeviceProtocol    = x%02X", desc->bDeviceProtocol);
   1120   GoogleDbgPrint("\n      bMaxPacketSize     = %u", desc->bMaxPacketSize0);
   1121   GoogleDbgPrint("\n      idVendor           = x%04X", desc->idVendor);
   1122   GoogleDbgPrint("\n      idProduct          = x%04X", desc->idProduct);
   1123   GoogleDbgPrint("\n      bcdDevice          = x%02X", desc->bcdDevice);
   1124   GoogleDbgPrint("\n      iManufacturer      = %u", desc->iManufacturer);
   1125   GoogleDbgPrint("\n      iProduct           = %u", desc->iProduct);
   1126   GoogleDbgPrint("\n      iSerialNumber      = %u", desc->iSerialNumber);
   1127   GoogleDbgPrint("\n      bNumConfigurations = %u", desc->bNumConfigurations);
   1128 }
   1129 
   1130 void AndroidUsbDeviceObject::PrintUsbTargedDeviceInformation(
   1131     const WDF_USB_DEVICE_INFORMATION* info) {
   1132   GoogleDbgPrint("\n***** WDF_USB_DEVICE_INFORMATION %p for device %p", info, this);
   1133   GoogleDbgPrint("\n      HcdPortCapabilities               = x%08X", info->HcdPortCapabilities);
   1134   GoogleDbgPrint("\n      Traits                            = x%08X", info->Traits);
   1135   GoogleDbgPrint("\n      VersionInfo.USBDI_Version         = x%08X",
   1136            info->UsbdVersionInformation.USBDI_Version);
   1137   GoogleDbgPrint("\n      VersionInfo.Supported_USB_Version = x%08X",
   1138            info->UsbdVersionInformation.Supported_USB_Version);
   1139 }
   1140 
   1141 void AndroidUsbDeviceObject::PrintConfigDescriptor(
   1142     const USB_CONFIGURATION_DESCRIPTOR* desc,
   1143     ULONG size) {
   1144   GoogleDbgPrint("\n***** USB_CONFIGURATION_DESCRIPTOR %p for device %p size %u",
   1145            desc, this, size);
   1146   GoogleDbgPrint("\n      bDescriptorType     = %u", desc->bDescriptorType);
   1147   GoogleDbgPrint("\n      wTotalLength        = %u", desc->wTotalLength);
   1148   GoogleDbgPrint("\n      bNumInterfaces      = %u", desc->bNumInterfaces);
   1149   GoogleDbgPrint("\n      bConfigurationValue = %u", desc->bConfigurationValue);
   1150   GoogleDbgPrint("\n      iConfiguration      = %u", desc->iConfiguration);
   1151   GoogleDbgPrint("\n      bmAttributes        = %u", desc->bmAttributes);
   1152   GoogleDbgPrint("\n      MaxPower            = %u", desc->MaxPower);
   1153 }
   1154 
   1155 void AndroidUsbDeviceObject::PrintSelectedConfig(
   1156     const WDF_USB_DEVICE_SELECT_CONFIG_PARAMS* config) {
   1157   GoogleDbgPrint("\n***** WDF_USB_DEVICE_SELECT_CONFIG_PARAMS %p for device %p", config, this);
   1158   GoogleDbgPrint("\n      Type = %u", config->Type);
   1159   switch (config->Type) {
   1160     case WdfUsbTargetDeviceSelectConfigTypeSingleInterface:
   1161       GoogleDbgPrint("\n      SingleInterface:");
   1162       GoogleDbgPrint("\n         NumberConfiguredPipes  = %u",
   1163                config->Types.SingleInterface.NumberConfiguredPipes);
   1164       GoogleDbgPrint("\n         ConfiguredUsbInterface = %p",
   1165                config->Types.SingleInterface.ConfiguredUsbInterface);
   1166       break;
   1167 
   1168     case WdfUsbTargetDeviceSelectConfigTypeMultiInterface:
   1169       GoogleDbgPrint("\n      MultiInterface:");
   1170       GoogleDbgPrint("\n         NumberInterfaces              = %u",
   1171                config->Types.MultiInterface.NumberInterfaces);
   1172       GoogleDbgPrint("\n         NumberOfConfiguredInterfaces  = %u",
   1173                config->Types.MultiInterface.NumberOfConfiguredInterfaces);
   1174       GoogleDbgPrint("\n         Pairs                         = %p",
   1175                config->Types.MultiInterface.Pairs);
   1176       break;
   1177 
   1178     case WdfUsbTargetDeviceSelectConfigTypeInterfacesDescriptor:
   1179       GoogleDbgPrint("\n      Descriptor:");
   1180       GoogleDbgPrint("\n         NumInterfaceDescriptors = %u",
   1181                config->Types.Descriptor.NumInterfaceDescriptors);
   1182       GoogleDbgPrint("\n         ConfigurationDescriptor = %p",
   1183                config->Types.Descriptor.ConfigurationDescriptor);
   1184       GoogleDbgPrint("\n         InterfaceDescriptors    = %p",
   1185                config->Types.Descriptor.InterfaceDescriptors);
   1186       break;
   1187 
   1188     case WdfUsbTargetDeviceSelectConfigTypeUrb:
   1189       GoogleDbgPrint("\n      Urb:");
   1190       GoogleDbgPrint("\n         Urb = %p",
   1191                config->Types.Urb.Urb);
   1192       break;
   1193 
   1194     case WdfUsbTargetDeviceSelectConfigTypeInterfacesPairs:
   1195     case WdfUsbTargetDeviceSelectConfigTypeInvalid:
   1196     case WdfUsbTargetDeviceSelectConfigTypeDeconfig:
   1197     default:
   1198       GoogleDbgPrint("\n      Config type is unknown or invalid or not printable.");
   1199       break;
   1200   }
   1201 }
   1202 
   1203 void AndroidUsbDeviceObject::PrintInterfaceDescriptor(
   1204     const USB_INTERFACE_DESCRIPTOR* desc) {
   1205   GoogleDbgPrint("\n***** USB_INTERFACE_DESCRIPTOR %p for device %p",
   1206            desc, this);
   1207   GoogleDbgPrint("\n      bLength            = %u", desc->bLength);
   1208   GoogleDbgPrint("\n      bDescriptorType    = %u", desc->bDescriptorType);
   1209   GoogleDbgPrint("\n      bInterfaceNumber   = %u", desc->bInterfaceNumber);
   1210   GoogleDbgPrint("\n      bAlternateSetting  = %u", desc->bAlternateSetting);
   1211   GoogleDbgPrint("\n      bNumEndpoints      = %u", desc->bNumEndpoints);
   1212   GoogleDbgPrint("\n      bInterfaceClass    = x%02X", desc->bInterfaceClass);
   1213   GoogleDbgPrint("\n      bInterfaceSubClass = x%02X", desc->bInterfaceSubClass);
   1214   GoogleDbgPrint("\n      bInterfaceProtocol = x%02X", desc->bInterfaceProtocol);
   1215   GoogleDbgPrint("\n      iInterface         = %u", desc->iInterface);
   1216 }
   1217 
   1218 void AndroidUsbDeviceObject::PrintPipeInformation(
   1219     const WDF_USB_PIPE_INFORMATION* info,
   1220     UCHAR pipe_index) {
   1221   GoogleDbgPrint("\n***** WDF_USB_PIPE_INFORMATION[%u] %p for device %p",
   1222            pipe_index, info, this);
   1223   GoogleDbgPrint("\n      Size                = %u", info->Size);
   1224   GoogleDbgPrint("\n      MaximumPacketSize   = %u", info->MaximumPacketSize);
   1225   GoogleDbgPrint("\n      EndpointAddress     = x%02X", info->EndpointAddress);
   1226   GoogleDbgPrint("\n      Interval            = %u", info->Interval);
   1227   GoogleDbgPrint("\n      SettingIndex        = %u", info->SettingIndex);
   1228   GoogleDbgPrint("\n      PipeType            = %u", info->PipeType);
   1229   GoogleDbgPrint("\n      MaximumTransferSize = %u", info->MaximumTransferSize);
   1230 }
   1231 
   1232 #endif  // DBG
   1233 
   1234 #pragma data_seg()
   1235 #pragma code_seg()
   1236