• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
wdf_pipe()240   __forceinline WDFUSBPIPE wdf_pipe() const {
241     return wdf_pipe_;
242   }
243 
244   /// Gets maximum transfer size for this pipe
max_transfer_size()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
max_packet_size()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.
GetTransferGranularity()260   __forceinline ULONG GetTransferGranularity() const {
261     return max_transfer_size();
262   }
263 
264   /// Checks if this is an input pipe
is_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
is_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
IsPipeAttached()277   __forceinline bool IsPipeAttached() const {
278     return (NULL != wdf_pipe());
279   }
280 
281   /// Gets USBD pipe handle
282   // TODO: Can we cache this?
usbd_pipe()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?
wdf_pipe_io_target()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