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