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 #ifndef ANDROID_USB_DEVICE_OBJECT_H__
     18 #define ANDROID_USB_DEVICE_OBJECT_H__
     19 /** \file
     20   This file consists of declaration of class AndroidUsbDeviceObject that
     21   encapsulates an extension for KMDF device (FDO) object.
     22 */
     23 
     24 #include "android_usb_wdf_object.h"
     25 
     26 // Forward declaration for file object extension
     27 class AndroidUsbFileObject;
     28 
     29 /** AndroidUsbDeviceObject class encapsulates an extension for KMDF FDO device
     30   object. Instances of this class must be allocated from NonPagedPool.
     31 */
     32 class AndroidUsbDeviceObject : public AndroidUsbWdfObject {
     33  public:
     34   /** \brief Constructs the object.
     35 
     36     This method must be called at low IRQL.
     37   */
     38   AndroidUsbDeviceObject();
     39 
     40   /** \brief Destructs the object.
     41 
     42     This method can be called at any IRQL.
     43   */
     44    ~AndroidUsbDeviceObject();
     45 
     46  public:
     47   /** \brief Creates and initializes FDO device object extension
     48 
     49     This method is called from driver's OnAddDevice method in response to
     50     AddDevice call from the PnP manager
     51     @param device_init[in] A pointer to a framework-allocated WDFDEVICE_INIT
     52            structure.
     53     @return If the routine succeeds, it returns STATUS_SUCCESS. Otherwise,
     54             it returns one of the error status values defined in ntstatus.h.
     55   */
     56   NTSTATUS CreateFDODevice(PWDFDEVICE_INIT device_init);
     57 
     58   /** \brief Resets target device
     59 
     60     When executing this method instance of this class may be deleted!
     61     This method must be called at PASSIVE IRQL.
     62     @return STATUS_SUCCESS or an appropriate error code
     63   */
     64   NTSTATUS ResetDevice();
     65 
     66  private:
     67   /** \name Device event handlers and callbacks
     68   */
     69   ///@{
     70 
     71   /** \brief Handler for PnP prepare hardware event
     72 
     73     This method performs any operations that are needed to make a device
     74     accessible to the driver. The framework calls this callback after the PnP
     75     manager has assigned hardware resources to the device and after the device
     76     has entered its uninitialized D0 state. This callback is called before
     77     calling the driver's EvtDeviceD0Entry callback function.
     78     This method is called at PASSIVE IRQL.
     79     @param resources_raw[in] A handle to a framework resource-list object that
     80            identifies the raw hardware resources that the PnP manager has
     81            assigned to the device.
     82     @param resources_translated[in] A handle to a framework resource-list
     83            object that identifies the translated hardware resources that the
     84            PnP manager has assigned to the device.
     85     @return Successful status or an appropriate error code
     86   */
     87   NTSTATUS OnEvtDevicePrepareHardware(WDFCMRESLIST resources_raw,
     88                                       WDFCMRESLIST resources_translated);
     89 
     90   /** \brief Handler for PnP release hardware event
     91 
     92     This method performs operations that  that are needed when a device is no
     93     longer accessible. Framework calls the callback function if the device is
     94     being removed, or if the PnP manager is attempting to redistribute hardware
     95     resources. The framework calls the EvtDeviceReleaseHardware callback
     96     function after the driver's device has been shut off, the PnP manager has
     97     reclaimed the hardware resources that it assigned to the device, and the
     98     device is no longer accessible. (The PCI configuration state is still
     99     accessible.) Typically, a EvtDeviceReleaseHardware callback function unmaps
    100     memory that the driver's EvtDevicePrepareHardware callback function mapped.
    101     Usually, all other hardware shutdown operations should take place in the
    102     driver's EvtDeviceD0Exit callback function.
    103     This method is called at PASSIVE IRQL.
    104     @param wdf_device[in] A handle to a framework device object.
    105     @param resources_translated[in] A handle to a framework resource-list
    106            object that identifies the translated hardware resources that the
    107            PnP manager has assigned to the device.
    108     @return Successful status or an appropriate error code
    109   */
    110   NTSTATUS OnEvtDeviceReleaseHardware(WDFCMRESLIST resources_translated);
    111 
    112   /** \brief Handler for create file event (request)
    113 
    114     This method performs operations that are needed when an application
    115     requests access to an item within this device path (including device
    116     itself). This method is called synchronously, in the context of the
    117     user thread that opens the item.
    118     This method is called at PASSIVE IRQL.
    119     @param request[in] A handle to a framework request object that represents
    120            a file creation request.
    121     @param wdf_fo[in] A handle to a framework file object that describes a
    122            file that is being created with this request.
    123     @return Successful status or an appropriate error code
    124   */
    125   void OnEvtDeviceFileCreate(WDFREQUEST request, WDFFILEOBJECT wdf_fo);
    126 
    127   /** \brief Entry point for PnP prepare hardware event
    128 
    129     This callback performs any operations that are needed to make a device
    130     accessible to the driver. The framework calls this callback after the PnP
    131     manager has assigned hardware resources to the device and after the device
    132     has entered its uninitialized D0 state. This callback is called before
    133     calling the driver's EvtDeviceD0Entry callback function.
    134     This callback is called at PASSIVE IRQL.
    135     @param wdf_dev[in] A handle to a framework device object.
    136     @param resources_raw[in] A handle to a framework resource-list object that
    137            identifies the raw hardware resources that the PnP manager has
    138            assigned to the device.
    139     @param resources_translated[in] A handle to a framework resource-list
    140            object that identifies the translated hardware resources that the
    141            PnP manager has assigned to the device.
    142     @return Successful status or an appropriate error code
    143   */
    144   static NTSTATUS EvtDevicePrepareHardwareEntry(WDFDEVICE wdf_dev,
    145                                                 WDFCMRESLIST resources_raw,
    146                                                 WDFCMRESLIST resources_translated);
    147 
    148   /** \brief Entry point for PnP release hardware event
    149 
    150     This callback performs operations that  that are needed when a device is no
    151     longer accessible. Framework calls the callback function if the device is
    152     being removed, or if the PnP manager is attempting to redistribute hardware
    153     resources. The framework calls the EvtDeviceReleaseHardware callback
    154     function after the driver's device has been shut off, the PnP manager has
    155     reclaimed the hardware resources that it assigned to the device, and the
    156     device is no longer accessible. (The PCI configuration state is still
    157     accessible.) Typically, a EvtDeviceReleaseHardware callback function unmaps
    158     memory that the driver's EvtDevicePrepareHardware callback function mapped.
    159     Usually, all other hardware shutdown operations should take place in the
    160     driver's EvtDeviceD0Exit callback function.
    161     This callback is called at PASSIVE IRQL.
    162     @param wdf_dev[in] A handle to a framework device object.
    163     @param resources_translated[in] A handle to a framework resource-list
    164            object that identifies the translated hardware resources that the
    165            PnP manager has assigned to the device.
    166     @return Successful status or an appropriate error code
    167   */
    168   static NTSTATUS EvtDeviceReleaseHardwareEntry(WDFDEVICE wdf_dev,
    169                                                 WDFCMRESLIST resources_translated);
    170 
    171   /** \brief Entry point for create file event (request)
    172 
    173     This callback performs operations that that are needed when an application
    174     requests access to a device. The framework calls a driver's
    175     EvtDeviceFileCreate callback function when a user application or another
    176     driver opens the device (or file on this device) to perform an I/O
    177     operation, such as reading or writing a file. This callback function is
    178     called synchronously, in the context of the user thread that opens the
    179     device.
    180     This callback is called at PASSIVE IRQL.
    181     @param wdf_dev[in] A handle to a framework device object.
    182     @param request[in] A handle to a framework request object that represents
    183            a file creation request.
    184     @param wdf_fo[in] A handle to a framework file object that describes a
    185            file that is being created with this request.
    186     @return Successful status or an appropriate error code
    187   */
    188   static void EvtDeviceFileCreateEntry(WDFDEVICE wdf_dev,
    189                                        WDFREQUEST request,
    190                                        WDFFILEOBJECT wdf_fo);
    191 
    192   ///@}
    193 
    194  private:
    195   /** \name I/O request event handlers and callbacks
    196   */
    197   ///@{
    198 
    199   /** \brief Read event handler
    200 
    201     This method is called when a read request comes to a file object opened
    202     on this device.
    203     This method can be called IRQL <= DISPATCH_LEVEL.
    204     @param request[in] A handle to a framework request object.
    205     @param length[in] The number of bytes to be read.
    206   */
    207   void OnEvtIoRead(WDFREQUEST request, size_t length);
    208 
    209   /** \brief Write event handler
    210 
    211     This method is called when a write request comes to a file object opened
    212     on this device.
    213     This method can be called IRQL <= DISPATCH_LEVEL.
    214     @param request[in] A handle to a framework request object.
    215     @param length[in] The number of bytes to be written.
    216   */
    217   void OnEvtIoWrite(WDFREQUEST request, size_t length);
    218 
    219   /** \brief IOCTL event handler
    220 
    221     This method is called when a device control request comes to a file object
    222     opened on this device.
    223     This method can be called IRQL <= DISPATCH_LEVEL.
    224     @param request[in] A handle to a framework request object.
    225     @param output_buf_len[in] The length, in bytes, of the request's output
    226            buffer, if an output buffer is available.
    227     @param input_buf_len[in] The length, in bytes, of the request's input
    228            buffer, if an input buffer is available.
    229     @param ioctl_code[in] The driver-defined or system-defined I/O control code
    230            that is associated with the request.
    231   */
    232   void OnEvtIoDeviceControl(WDFREQUEST request,
    233                             size_t output_buf_len,
    234                             size_t input_buf_len,
    235                             ULONG ioctl_code);
    236 
    237   /** \brief Entry point for read event
    238 
    239     This callback is called when a read request comes to a file object opened
    240     on this device.
    241     This callback can be called IRQL <= DISPATCH_LEVEL.
    242     @param queue[in] A handle to the framework queue object that is associated
    243            with the I/O request.
    244     @param request[in] A handle to a framework request object.
    245     @param length[in] The number of bytes to be read.
    246   */
    247   static void EvtIoReadEntry(WDFQUEUE queue,
    248                              WDFREQUEST request,
    249                              size_t length);
    250 
    251   /** \brief Entry point for write event
    252 
    253     This callback is called when a write request comes to a file object opened
    254     on this device.
    255     This callback can be called IRQL <= DISPATCH_LEVEL.
    256     @param queue[in] A handle to the framework queue object that is associated
    257            with the I/O request.
    258     @param request[in] A handle to a framework request object.
    259     @param length[in] The number of bytes to be written.
    260   */
    261   static void EvtIoWriteEntry(WDFQUEUE queue,
    262                               WDFREQUEST request,
    263                               size_t length);
    264 
    265   /** \brief Entry point for device IOCTL event
    266 
    267     This callback is called when a device control request comes to a file
    268     object opened on this device.
    269     This callback can be called IRQL <= DISPATCH_LEVEL.
    270     @param queue[in] A handle to the framework queue object that is associated
    271            with the I/O request.
    272     @param request[in] A handle to a framework request object.
    273     @param output_buf_len[in] The length, in bytes, of the request's output
    274            buffer, if an output buffer is available.
    275     @param input_buf_len[in] The length, in bytes, of the request's input
    276            buffer, if an input buffer is available.
    277     @param ioctl_code[in] The driver-defined or system-defined I/O control code
    278            that is associated with the request.
    279   */
    280   static void EvtIoDeviceControlEntry(WDFQUEUE queue,
    281                                       WDFREQUEST request,
    282                                       size_t output_buf_len,
    283                                       size_t input_buf_len,
    284                                       ULONG ioctl_code);
    285 
    286   ///@}
    287 
    288  public:
    289   /** \name Device level I/O request handlers
    290   */
    291   ///@{
    292 
    293   /** \brief Gets USB device descriptor
    294 
    295     This method can be called at IRQL <= DISPATCH_LEVEL
    296     @param request[in] A handle to a framework request object for this IOCTL.
    297     @param output_buf_len[in] The length, in bytes, of the request's output
    298            buffer, if an output buffer is available.
    299   */
    300   void OnGetUsbDeviceDescriptorCtl(WDFREQUEST request, size_t output_buf_len);
    301 
    302   /** \brief Gets USB configuration descriptor for the selected configuration.
    303 
    304     This method can be called at IRQL <= DISPATCH_LEVEL
    305     @param request[in] A handle to a framework request object for this IOCTL.
    306     @param output_buf_len[in] The length, in bytes, of the request's output
    307            buffer, if an output buffer is available.
    308   */
    309   void OnGetUsbConfigDescriptorCtl(WDFREQUEST request, size_t output_buf_len);
    310 
    311   /** \brief Gets USB configuration descriptor for the selected interface.
    312 
    313     This method can be called at IRQL <= DISPATCH_LEVEL
    314     @param request[in] A handle to a framework request object for this IOCTL.
    315     @param output_buf_len[in] The length, in bytes, of the request's output
    316            buffer, if an output buffer is available.
    317   */
    318   void OnGetUsbInterfaceDescriptorCtl(WDFREQUEST request, size_t output_buf_len);
    319 
    320   /** \brief Gets information about an endpoint.
    321 
    322     This method can be called at IRQL <= DISPATCH_LEVEL
    323     @param request[in] A handle to a framework request object for this IOCTL.
    324     @param input_buf_len[in] The length, in bytes, of the request's input
    325            buffer, if an input buffer is available.
    326     @param output_buf_len[in] The length, in bytes, of the request's output
    327            buffer, if an output buffer is available.
    328   */
    329   void OnGetEndpointInformationCtl(WDFREQUEST request,
    330                                    size_t input_buf_len,
    331                                    size_t output_buf_len);
    332 
    333   /** \brief Gets device serial number.
    334 
    335     Serial number is returned in form of zero-terminated string that in the
    336     output buffer. This method must be called at low IRQL.
    337     @param request[in] A handle to a framework request object for this IOCTL.
    338     @param output_buf_len[in] The length, in bytes, of the request's output
    339            buffer, if an output buffer is available.
    340   */
    341   void OnGetSerialNumberCtl(WDFREQUEST request, size_t output_buf_len);
    342 
    343   ///@}
    344 
    345  private:
    346   /** \name Internal methods
    347   */
    348   ///@{
    349 
    350   /** \brief Creates default request queue for this device.
    351 
    352     In KMDF all I/O requests are coming through the queue object. So, in order
    353     to enable our device to receive I/O requests we must create a queue for it.
    354     This method is called at PASSIVE IRQL.
    355     @return STATUS_SUCCESS or an appropriate error code.
    356   */
    357   NTSTATUS CreateDefaultQueue();
    358 
    359   /** \brief Configures our device.
    360 
    361     This method is called from the prepare hardware handler after underlying
    362     FDO device has been created.
    363     This method is called at PASSSIVE IRQL.
    364     @return STATUS_SUCCESS or an appropriate error code.
    365   */
    366   NTSTATUS ConfigureDevice();
    367 
    368   /** \brief Selects interfaces on our device.
    369 
    370     This method is called from the prepare hardware handler after underlying
    371     FDO device has been created and configured.
    372     This method is called at PASSSIVE IRQL.
    373     @return STATUS_SUCCESS or an appropriate error code.
    374   */
    375   NTSTATUS SelectInterfaces();
    376 
    377   /** \brief Gets pipe index from a file name
    378 
    379     This method is called from OnEvtDeviceFileCreate to determine index of
    380     the pipe this file is addressing.
    381     This method is called at PASSIVE IRQL.
    382     @param file_path[in] Path to the file that being opened.
    383     @return Pipe index or INVALID_UCHAR if index cannot be calculated.
    384   */
    385   UCHAR GetPipeIndexFromFileName(PUNICODE_STRING file_path);
    386 
    387   /** \brief Creates file object extension for a pipe
    388 
    389     This method is called from OnEvtDeviceFileCreate to create an appropriate
    390     file object extension for a particular pipe type.
    391     This method is called at PASSIVE IRQL.
    392     @param wdf_fo[in] KMDF file to extend.
    393     @param wdf_pipe_obj[in] KMDF pipe for this extension
    394     @param pipe_info[in] Pipe information
    395     @param wdf_file_ext[out] Upon successfull completion will receive instance
    396            of the extension.
    397     @return STATUS_SUCCESS or an appropriate error code
    398   */
    399   NTSTATUS CreatePipeFileObjectExt(WDFFILEOBJECT wdf_fo,
    400                                    WDFUSBPIPE wdf_pipe_obj,
    401                                    const WDF_USB_PIPE_INFORMATION* pipe_info,
    402                                    AndroidUsbFileObject** wdf_file_ext);
    403 
    404   ///@}
    405 
    406  private:
    407   /** \name Debugging support
    408   */
    409   ///@{
    410 
    411 #if DBG
    412   /// Prints USB_DEVICE_DESCRIPTOR to debug output
    413   void PrintUsbDeviceDescriptor(const USB_DEVICE_DESCRIPTOR* desc);
    414 
    415   /// Prints WDF_USB_DEVICE_INFORMATION to debug output
    416   void PrintUsbTargedDeviceInformation(const WDF_USB_DEVICE_INFORMATION* info);
    417 
    418   /// Prints USB_CONFIGURATION_DESCRIPTOR to debug output
    419   void PrintConfigDescriptor(const USB_CONFIGURATION_DESCRIPTOR* desc,
    420                              ULONG size);
    421 
    422   /// Prints WDF_USB_DEVICE_SELECT_CONFIG_PARAMS to debug output
    423   void PrintSelectedConfig(const WDF_USB_DEVICE_SELECT_CONFIG_PARAMS* config);
    424 
    425   /// Prints USB_INTERFACE_DESCRIPTOR to debug output
    426   void PrintInterfaceDescriptor(const USB_INTERFACE_DESCRIPTOR* desc);
    427 
    428   /// Prints WDF_USB_PIPE_INFORMATION to debug output
    429   void PrintPipeInformation(const WDF_USB_PIPE_INFORMATION* info,
    430                             UCHAR pipe_index);
    431 
    432 #endif  // DBG
    433 
    434   ///@}
    435 
    436  public:
    437   /// Gets WDF device handle for this device
    438   __forceinline WDFDEVICE wdf_device() const {
    439     return reinterpret_cast<WDFDEVICE>(wdf_object());
    440   }
    441 
    442   /// Gets target USB device descriptor
    443   __forceinline const USB_DEVICE_DESCRIPTOR* usb_device_descriptor() const {
    444     return &usb_device_descriptor_;
    445   }
    446 
    447   /// Gets target USB device information
    448   __forceinline const WDF_USB_DEVICE_INFORMATION* usb_device_info() const {
    449     return &usb_device_info_;
    450   }
    451 
    452   /// Gets selected interface descriptor
    453   __forceinline const USB_INTERFACE_DESCRIPTOR* interface_descriptor() const {
    454     return &interface_descriptor_;
    455   }
    456 
    457   /// Gets target (PDO) device handle
    458   __forceinline WDFUSBDEVICE wdf_target_device() const {
    459     return wdf_target_device_;
    460   }
    461 
    462   /// Checks if target device has been created
    463   __forceinline bool IsTaretDeviceCreated() const {
    464     return (NULL != wdf_target_device());
    465   }
    466 
    467   /// Gets USB configuration descriptor
    468   __forceinline const USB_CONFIGURATION_DESCRIPTOR* configuration_descriptor() const {
    469     return configuration_descriptor_;
    470   }
    471 
    472   /// Checks if device has been configured
    473   __forceinline bool IsDeviceConfigured() const {
    474     return (NULL != configuration_descriptor());
    475   }
    476 
    477   /// Gets number of interfaces for this device
    478   __forceinline UCHAR GetInterfaceCount() const {
    479     ASSERT(IsDeviceConfigured());
    480     return IsDeviceConfigured() ? configuration_descriptor()->bNumInterfaces : 0;
    481   }
    482 
    483   /// Checks if this is "single interface" device
    484   __forceinline bool IsSingleInterfaceDevice() const {
    485     return (1 == GetInterfaceCount());
    486   }
    487 
    488   /// Gets USB interface selected on this device
    489   __forceinline WDFUSBINTERFACE wdf_usb_interface() const {
    490     return wdf_usb_interface_;
    491   }
    492 
    493   /// Checks if an interface has been selected on this device
    494   __forceinline bool IsInterfaceSelected() const {
    495     return (NULL != wdf_usb_interface());
    496   }
    497 
    498   /// Gets number of pipes configured on this device
    499   __forceinline UCHAR configured_pipes_num() const {
    500     return configured_pipes_num_;
    501   }
    502 
    503   /// Gets index of the bulk read pipe
    504   __forceinline UCHAR bulk_read_pipe_index() const {
    505     return bulk_read_pipe_index_;
    506   }
    507 
    508   /// Gets index of the bulk write pipe
    509   __forceinline UCHAR bulk_write_pipe_index() const {
    510     return bulk_write_pipe_index_;
    511   }
    512 
    513   /// Checks if this is a high speed device
    514   __forceinline bool IsHighSpeed() const {
    515     return (0 != (usb_device_info()->Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED));
    516   }
    517 
    518   /// Checks if bulk read pipe index is known
    519   __forceinline bool IsBulkReadPipeKnown() const {
    520     return (INVALID_UCHAR != bulk_read_pipe_index());
    521   }
    522 
    523   /// Checks if bulk write pipe index is known
    524   __forceinline bool IsBulkWritePipeKnown() const {
    525     return (INVALID_UCHAR != bulk_write_pipe_index());
    526   }
    527 
    528   /// Gets device serial number string. Note that string may be
    529   /// not zero-terminated. Use serial_number_len() to get actual
    530   /// length of this string.
    531   __forceinline const WCHAR* serial_number() const {
    532     ASSERT(NULL != serial_number_handle_);
    533     return (NULL != serial_number_handle_) ?
    534       reinterpret_cast<const WCHAR*>
    535         (WdfMemoryGetBuffer(serial_number_handle_, NULL)) :
    536       NULL;
    537   }
    538 
    539   /// Gets length (in bytes) of device serial number string
    540   __forceinline USHORT serial_number_char_len() const {
    541     return serial_number_char_len_;
    542   }
    543 
    544   /// Gets length (in bytes) of device serial number string
    545   __forceinline USHORT serial_number_byte_len() const {
    546     return serial_number_char_len() * sizeof(WCHAR);
    547   }
    548 
    549  protected:
    550   /// Target USB device descriptor
    551   USB_DEVICE_DESCRIPTOR         usb_device_descriptor_;
    552 
    553   /// Target USB device information
    554   WDF_USB_DEVICE_INFORMATION    usb_device_info_;
    555 
    556   /// Selected interface descriptor
    557   USB_INTERFACE_DESCRIPTOR      interface_descriptor_;
    558 
    559   /// USB configuration descriptor
    560   PUSB_CONFIGURATION_DESCRIPTOR configuration_descriptor_;
    561 
    562   /// Target (PDO?) device handle
    563   WDFUSBDEVICE                  wdf_target_device_;
    564 
    565   /// USB interface selected on this device
    566   WDFUSBINTERFACE               wdf_usb_interface_;
    567 
    568   /// Device serial number
    569   WDFMEMORY                     serial_number_handle_;
    570 
    571   /// Device serial number string length
    572   USHORT                        serial_number_char_len_;
    573 
    574   /// Number of pipes configured on this device
    575   UCHAR                         configured_pipes_num_;
    576 
    577   /// Index of the bulk read pipe
    578   UCHAR                         bulk_read_pipe_index_;
    579 
    580   /// Index of the bulk write pipe
    581   UCHAR                         bulk_write_pipe_index_;
    582 };
    583 
    584 /** \brief Gets device KMDF object extension for the given KMDF object
    585 
    586   @param wdf_dev[in] KMDF handle describing device object
    587   @return Instance of AndroidUsbDeviceObject associated with KMDF object or
    588           NULL if association is not found.
    589 */
    590 __forceinline AndroidUsbDeviceObject* GetAndroidUsbDeviceObjectFromHandle(
    591     WDFDEVICE wdf_dev) {
    592   AndroidUsbWdfObject* wdf_object_ext =
    593     GetAndroidUsbWdfObjectFromHandle(wdf_dev);
    594   ASSERT((NULL != wdf_object_ext) &&
    595          wdf_object_ext->Is(AndroidUsbWdfObjectTypeDevice));
    596   if ((NULL != wdf_object_ext) &&
    597       wdf_object_ext->Is(AndroidUsbWdfObjectTypeDevice)) {
    598     return reinterpret_cast<AndroidUsbDeviceObject*>(wdf_object_ext);
    599   }
    600   return NULL;
    601 }
    602 
    603 #endif  // ANDROID_USB_DEVICE_OBJECT_H__
    604