• 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 /** \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 
AndroidUsbDeviceObject()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 
~AndroidUsbDeviceObject()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 
CreateFDODevice(PWDFDEVICE_INIT device_init)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 
ResetDevice()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 
OnEvtDevicePrepareHardware(WDFCMRESLIST resources_raw,WDFCMRESLIST resources_translated)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 
248     WdfUsbTargetDeviceAllocAndQueryString(wdf_target_device(),
249 
250                                           WDF_NO_OBJECT_ATTRIBUTES,
251 
252                                           &serial_number_handle_,
253 
254                                           &serial_number_char_len_,
255 
256                                           usb_device_descriptor_.iSerialNumber,
257 
258                                           0x0409);  // English (US)
259 
260   if (!NT_SUCCESS(status))
261 
262     return status;
263 
264 
265 
266 #if DBG
267 
268   UNICODE_STRING ser_num;
269 
270   ser_num.Length = serial_number_byte_len();
271 
272   ser_num.MaximumLength = ser_num.Length;
273 
274   ser_num.Buffer = const_cast<WCHAR*>
275 
276     (serial_number());
277 
278   GoogleDbgPrint("\n*** Device serial number %wZ", &ser_num);
279 
280 #endif  // DBG
281 
282 
283 
284   // 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())
OnEvtDeviceFileCreate(WDFREQUEST request,WDFFILEOBJECT wdf_fo)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();
EvtDevicePrepareHardwareEntry(WDFDEVICE wdf_dev,WDFCMRESLIST resources_raw,WDFCMRESLIST resources_translated)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);
EvtDeviceReleaseHardwareEntry(WDFDEVICE wdf_dev,WDFCMRESLIST resources_translated)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) ?
EvtDeviceFileCreateEntry(WDFDEVICE wdf_dev,WDFREQUEST request,WDFFILEOBJECT wdf_fo)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 
OnEvtIoRead(WDFREQUEST request,size_t length)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,
OnEvtIoWrite(WDFREQUEST request,size_t length)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,
OnEvtIoDeviceControl(WDFREQUEST request,size_t output_buf_len,size_t input_buf_len,ULONG ioctl_code)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());
EvtIoReadEntry(WDFQUEUE queue,WDFREQUEST request,size_t length)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   }
EvtIoWriteEntry(WDFQUEUE queue,WDFREQUEST request,size_t length)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,
OnGetUsbDeviceDescriptorCtl(WDFREQUEST request,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));
OnGetUsbConfigDescriptorCtl(WDFREQUEST request,size_t output_buf_len)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,
OnGetUsbInterfaceDescriptorCtl(WDFREQUEST request,size_t output_buf_len)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));
OnGetEndpointInformationCtl(WDFREQUEST request,size_t input_buf_len,size_t output_buf_len)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 =
OnGetSerialNumberCtl(WDFREQUEST request,size_t output_buf_len)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;
CreateDefaultQueue()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 
ConfigureDevice()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));
SelectInterfaces()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());
GetPipeIndexFromFileName(PUNICODE_STRING file_path)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') ||
CreatePipeFileObjectExt(WDFFILEOBJECT wdf_fo,WDFUSBPIPE wdf_pipe_obj,const WDF_USB_PIPE_INFORMATION * pipe_info,AndroidUsbFileObject ** wdf_file_ext)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.
PrintUsbDeviceDescriptor(const USB_DEVICE_DESCRIPTOR * desc)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()
PrintUsbTargedDeviceInformation(const WDF_USB_DEVICE_INFORMATION * info)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",
PrintSelectedConfig(const WDF_USB_DEVICE_SELECT_CONFIG_PARAMS * config)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);
PrintInterfaceDescriptor(const USB_INTERFACE_DESCRIPTOR * desc)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.");
PrintPipeInformation(const WDF_USB_PIPE_INFORMATION * info,UCHAR pipe_index)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