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_PIPE_FILE_OBJECT_H__
     18 #define ANDROID_USB_PIPE_FILE_OBJECT_H__
     19 /** \file
     20   This file consists of declaration of class AndroidUsbPipeFileObject that
     21   encapsulates a common extension for pipe file objects.
     22 */
     23 
     24 #include "android_usb_file_object.h"
     25 
     26 /** AndroidUsbPipeFileObject class encapsulates extension for a KMDF file
     27   object that represents opened pipe. Instances of this class must be
     28   allocated from NonPagedPool.
     29 */
     30 class AndroidUsbPipeFileObject : public AndroidUsbFileObject {
     31  public:
     32   /** \brief Constructs the object.
     33 
     34     This method must be called at low IRQL.
     35     @param dev_obj[in] Our device object for which this file has been created
     36     @param wdf_fo[in] KMDF file object this extension wraps
     37     @param wdf_pipe_obj[in] KMDF pipe for this file
     38   */
     39   AndroidUsbPipeFileObject(AndroidUsbDeviceObject* dev_obj,
     40                            WDFFILEOBJECT wdf_fo,
     41                            WDFUSBPIPE wdf_pipe_obj);
     42 
     43   /** \brief Destructs the object.
     44 
     45     This method can be called at any IRQL.
     46   */
     47    virtual ~AndroidUsbPipeFileObject();
     48 
     49   /** \brief Initializes the pipe file object extension
     50 
     51     This method internally calls AndroidUsbFileObject::Initialize()
     52     This method must be called at low IRQL
     53     @param pipe_info[in] Pipe information
     54     @return STATUS_SUCCESS or an appropriate error code
     55   */
     56   virtual NTSTATUS InitializePipe(const WDF_USB_PIPE_INFORMATION* pipe_info);
     57 
     58   /** \brief Read event handler
     59 
     60     This method is called when a read request comes to the file object this
     61     extension wraps. This method is an override.
     62     This method can be called IRQL <= DISPATCH_LEVEL.
     63     @param request[in] A handle to a framework request object.
     64     @param length[in] The number of bytes to be read.
     65     @return Successful status or an appropriate error code
     66   */
     67   virtual void OnEvtIoRead(WDFREQUEST request, size_t length);
     68 
     69   /** \brief Write event handler
     70 
     71     This method is called when a write request comes to the file object this
     72     extension wraps. This method is an override.
     73     This method can be called IRQL <= DISPATCH_LEVEL.
     74     @param request[in] A handle to a framework request object.
     75     @param length[in] The number of bytes to be written.
     76     @return Successful status or an appropriate error code
     77   */
     78   virtual void OnEvtIoWrite(WDFREQUEST request, size_t length);
     79 
     80   /** \brief IOCTL event handler
     81 
     82     This method is called when a device control request comes to the file
     83     object this extension wraps. We hanlde the following IOCTLs here:
     84     1. ADB_CTL_GET_ENDPOINT_INFORMATION
     85     2. ADB_CTL_BULK_READ
     86     3. ADB_CTL_BULK_WRITE
     87     This method can be called IRQL <= DISPATCH_LEVEL.
     88     @param request[in] A handle to a framework request object.
     89     @param output_buf_len[in] The length, in bytes, of the request's output
     90            buffer, if an output buffer is available.
     91     @param input_buf_len[in] The length, in bytes, of the request's input
     92            buffer, if an input buffer is available.
     93     @param ioctl_code[in] The driver-defined or system-defined I/O control code
     94            that is associated with the request.
     95     @return Successful status or an appropriate error code
     96   */
     97   virtual void OnEvtIoDeviceControl(WDFREQUEST request,
     98                                     size_t output_buf_len,
     99                                     size_t input_buf_len,
    100                                     ULONG ioctl_code);
    101 
    102  protected:
    103   /** \brief Handler for ADB_CTL_GET_ENDPOINT_INFORMATION IOCTL request
    104 
    105     @param request[in] A handle to a framework request object.
    106     @param output_buf_len[in] The length, in bytes, of the request's output
    107            buffer, if an output buffer is available.
    108   */
    109   virtual void OnCtlGetEndpointInformation(WDFREQUEST request,
    110                                            size_t output_buf_len);
    111 
    112   /** \brief Handler for ADB_CTL_BULK_READ IOCTL request
    113 
    114     @param request[in] A handle to a framework request object.
    115     @param output_buf_len[in] The length, in bytes, of the request's output
    116            buffer, if an output buffer is available.
    117     @param input_buf_len[in] The length, in bytes, of the request's input
    118            buffer, if an input buffer is available.
    119   */
    120   virtual void OnCtlBulkRead(WDFREQUEST request,
    121                              size_t output_buf_len,
    122                              size_t input_buf_len);
    123 
    124   /** \brief Handler for ADB_CTL_BULK_WRITE IOCTL request
    125 
    126     @param request[in] A handle to a framework request object.
    127     @param output_buf_len[in] The length, in bytes, of the request's output
    128            buffer, if an output buffer is available.
    129     @param input_buf_len[in] The length, in bytes, of the request's input
    130            buffer, if an input buffer is available.
    131   */
    132   virtual void OnCtlBulkWrite(WDFREQUEST request,
    133                               size_t output_buf_len,
    134                               size_t input_buf_len);
    135 
    136   /** \brief Performs common bulk read / write on the pipe
    137 
    138     This method is called from bulk and interrupt pipe file extensions to
    139     perform read to / write from the pipe this file represents. Typicaly,
    140     this method is called from OnEvtIoRead / OnEvtIoWrite /
    141     OnEvtIoDeviceControl methods. One very special case for this method is
    142     IOCTL-originated write request. If this is IOCTL-originated write request
    143     we can't report transfer size through the request's status block. Instead,
    144     for IOCTL-originated writes, the output buffer must a) exist and b) point
    145     to an ULONG that will receive size of the transfer. Besides, for this type
    146     of writes we create / lock write buffer MDL ourselves so we need to unlock
    147     and free it in the completion routine.
    148     This method can be called at IRQL <= DISPATCH_LEVEL.
    149     @param request[in] A handle to a framework request object.
    150     @param transfer_mdl[in] MDL for the transferring buffer. The MDL must be
    151            locked prior to this call.
    152     @param length[in] The number of bytes to be read / written. If this method
    153            is actually IOCTL originated write request this parameter must be
    154            taken from AdbBulkTransfer.transfer_size by the caller of this
    155            method. AdbBulkTransfer is available at the beginning of the input
    156            buffer for bulk read / write IOCTLs.
    157     @param is_read[in] If true this is a read operation, otherwise it's write
    158            operation.
    159     @param time_out[in] Number of milliseconds for this request to complete.
    160            If this parameter is zero there will be no timeout associated with
    161            the request. Otherwise, if request doesn't complete within the given
    162            timeframe it will be cancelled.
    163     @param is_ioctl[in] If 'true' this method has been called from IOCTL
    164            handler. Otherwise it has been called from read / write handler. If
    165            this is IOCTL-originated write request we need to report bytes
    166            transferred through the IOCTL's output buffer.
    167     This method can be called IRQL <= DISPATCH_LEVEL.
    168     @return STATUS_SUCCESS or an appropriate error code
    169   */
    170   virtual NTSTATUS CommonBulkReadWrite(WDFREQUEST request,
    171                                        PMDL transfer_mdl,
    172                                        ULONG length,
    173                                        bool is_read,
    174                                        ULONG time_out,
    175                                        bool is_ioctl);
    176 
    177   /** \brief Handles request completion for CommonBulkReadWrite
    178 
    179     This method is called from CommonReadWriteCompletionEntry.
    180     This method can be called at IRQL <= DISPATCH_LEVEL.
    181     @param request[in] A handle to a framework request object that is being
    182            completed.
    183     @param params[in] A pointer to a WDF_REQUEST_COMPLETION_PARAMS structure
    184            that contains information about the completed request.
    185     @param context[in] Context associated with this request in
    186            CommonBulkReadWrite
    187     This method can be called IRQL <= DISPATCH_LEVEL.
    188   */
    189   virtual void OnCommonReadWriteCompletion(WDFREQUEST request,
    190                                            PWDF_REQUEST_COMPLETION_PARAMS completion_params,
    191                                            AndroidUsbWdfRequestContext* context);
    192 
    193   /** \brief Resets pipe associated with this file
    194 
    195     After reseting the pipe this object might be destroyed.
    196     This method must be called at PASSIVE IRQL.
    197     @param read_device_on_failure[in] If true and reset pipe has failed this
    198            method will attempt to reset the device.
    199     @return STATUS_SUCCESS on success or an appropriate error code
    200   */
    201   virtual NTSTATUS ResetPipe();
    202 
    203   /** \brief Queues a workitem to launch pipe reset at PASSIVE IRQL
    204 
    205     This method can be called at IRQL <= DISPATCH_LEVEL.
    206     @return STATUS_SUCCESS or an appropriate error code.
    207   */
    208   virtual NTSTATUS QueueResetPipePassiveCallback();
    209 
    210  private:
    211   /** \brief Request completion routine for CommonBulkReadWrite
    212 
    213     This method can be called at IRQL <= DISPATCH_LEVEL.
    214     @param request[in] A handle to a framework request object that is being
    215            completed.
    216     @param wdf_target[in] A handle to an I/O target object that represents the
    217            I/O target that completed the request. In this case this is a pipe.
    218     @param params[in] A pointer to a WDF_REQUEST_COMPLETION_PARAMS structure
    219            that contains information about the completed request.
    220     @param completion_context[in] A handle to driver-supplied context
    221            information, which the driver specified in a previous call to
    222            WdfRequestSetCompletionRoutine. In our case this is a pointer
    223            to this class instance that issued the request.
    224     This method can be called IRQL <= DISPATCH_LEVEL.
    225   */
    226   static void CommonReadWriteCompletionEntry(WDFREQUEST request,
    227                                              WDFIOTARGET wdf_target,
    228                                              PWDF_REQUEST_COMPLETION_PARAMS params,
    229                                              WDFCONTEXT completion_context);
    230 
    231   /** \brief Entry point for pipe reset workitem callback
    232 
    233     This method is called at PASSIVE IRQL
    234     @param wdf_work_item[in] A handle to a framework work item object.
    235   */
    236   static void ResetPipePassiveCallbackEntry(WDFWORKITEM wdf_work_item);
    237 
    238  public:
    239   /// Gets KMDF pipe handle for this file
    240   __forceinline WDFUSBPIPE wdf_pipe() const {
    241     return wdf_pipe_;
    242   }
    243 
    244   /// Gets maximum transfer size for this pipe
    245   __forceinline ULONG max_transfer_size() const {
    246     ASSERT(0 != pipe_information_.MaximumTransferSize);
    247     return pipe_information_.MaximumTransferSize;
    248   }
    249 
    250   /// Gets maximum packet size this pipe is capable of
    251   __forceinline ULONG max_packet_size() const {
    252     ASSERT(0 != pipe_information_.MaximumPacketSize);
    253     return pipe_information_.MaximumPacketSize;
    254   }
    255 
    256   /// Gets transfer granularity
    257   // TODO: It looks like device USB is capable of handling
    258   // packets with size greater than pipe_information_.MaximumPacketSize!
    259   // So, looks like we are not bound by this parameter in this driver.
    260   __forceinline ULONG GetTransferGranularity() const {
    261     return max_transfer_size();
    262   }
    263 
    264   /// Checks if this is an input pipe
    265   __forceinline bool is_input_pipe() const {
    266     return WDF_USB_PIPE_DIRECTION_IN(pipe_information_.EndpointAddress) ?
    267           true : false;
    268   }
    269 
    270   /// Checks if this is an output pipe
    271   __forceinline bool is_output_pipe() const {
    272     return WDF_USB_PIPE_DIRECTION_OUT(pipe_information_.EndpointAddress) ?
    273           true : false;
    274   }
    275 
    276   /// Checks if pipe is attached to this file
    277   __forceinline bool IsPipeAttached() const {
    278     return (NULL != wdf_pipe());
    279   }
    280 
    281   /// Gets USBD pipe handle
    282   // TODO: Can we cache this?
    283   __forceinline USBD_PIPE_HANDLE usbd_pipe() const {
    284     ASSERT(IsPipeAttached());
    285     return (IsPipeAttached()) ? WdfUsbTargetPipeWdmGetPipeHandle(wdf_pipe()) :
    286                                 NULL;
    287   }
    288 
    289   /// Gets I/O target handle for this pipe
    290   // TODO: Can we cache this?
    291   __forceinline WDFIOTARGET wdf_pipe_io_target() const {
    292     ASSERT(IsPipeAttached());
    293     return (IsPipeAttached()) ? WdfUsbTargetPipeGetIoTarget(wdf_pipe()) :
    294                                 NULL;
    295   }
    296 
    297  protected:
    298   /// Cached pipe information
    299   WDF_USB_PIPE_INFORMATION  pipe_information_;
    300 
    301   /// KMDF pipe handle for this file
    302   WDFUSBPIPE                wdf_pipe_;
    303 };
    304 
    305 #endif  // ANDROID_USB_PIPE_FILE_OBJECT_H__
    306