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 AndroidUsbDriverObject that
19 encapsulates our driver 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_driver_object.h"
27
28 #pragma data_seg()
29
30 /** Globally accessible instance of the AndroidUsbDriverObject.
31 NT OS design allows us using of a global pointer to our driver object
32 instance since it can't be created or destroyed concurently and its value
33 is not going to change between creation and destruction.
34 */
35 AndroidUsbDriverObject* global_driver_object = NULL;
36
37 #pragma code_seg("INIT")
38
39 extern "C" {
40
41 /// Main entry point to the driver
DriverEntry(PDRIVER_OBJECT drv_object,PUNICODE_STRING reg_path)42 NTSTATUS DriverEntry(PDRIVER_OBJECT drv_object, PUNICODE_STRING reg_path) {
43 // Just pass it down inside the class
44 return AndroidUsbDriverObject::DriverEntry(drv_object, reg_path);
45 }
46
47 } // extern "C"
48
DriverEntry(PDRIVER_OBJECT drv_object,PUNICODE_STRING reg_path)49 NTSTATUS AndroidUsbDriverObject::DriverEntry(PDRIVER_OBJECT drv_object,
50 PUNICODE_STRING reg_path) {
51 ASSERT_IRQL_PASSIVE();
52 ASSERT(NULL != drv_object);
53 ASSERT((NULL != reg_path) &&
54 (NULL != reg_path->Buffer) &&
55 (0 != reg_path->Length));
56
57 // Instantiate driver object
58 global_driver_object = new(NonPagedPool, GANDR_POOL_TAG_DRIVER_OBJECT)
59 AndroidUsbDriverObject(drv_object, reg_path);
60 ASSERT(NULL != global_driver_object);
61 if (NULL == global_driver_object)
62 return STATUS_INSUFFICIENT_RESOURCES;
63
64 // Initialize driver object
65 NTSTATUS status = global_driver_object->OnDriverEntry(drv_object, reg_path);
66
67 if (!NT_SUCCESS(status)) {
68 // Something went wrong. Delete our driver object and get out of here.
69 delete global_driver_object;
70 }
71
72 return status;
73 }
74
AndroidUsbDriverObject(PDRIVER_OBJECT drv_object,PUNICODE_STRING reg_path)75 AndroidUsbDriverObject::AndroidUsbDriverObject(PDRIVER_OBJECT drv_object,
76 PUNICODE_STRING reg_path)
77 : driver_object_(drv_object),
78 wdf_driver_(NULL) {
79 ASSERT_IRQL_PASSIVE();
80 ASSERT(NULL != driver_object());
81 }
82
OnDriverEntry(PDRIVER_OBJECT drv_object,PUNICODE_STRING reg_path)83 NTSTATUS AndroidUsbDriverObject::OnDriverEntry(PDRIVER_OBJECT drv_object,
84 PUNICODE_STRING reg_path) {
85 ASSERT_IRQL_PASSIVE();
86 ASSERT(driver_object() == drv_object);
87
88 // Initiialize driver config, specifying our unload callback and default
89 // pool tag for memory allocations that KMDF does on our behalf.
90 WDF_DRIVER_CONFIG config;
91 WDF_DRIVER_CONFIG_INIT(&config, EvtDeviceAddEntry);
92 config.EvtDriverUnload = EvtDriverUnloadEntry;
93 config.DriverPoolTag = GANDR_POOL_TAG_DEFAULT;
94
95 // Create a framework driver object to represent our driver.
96 NTSTATUS status = WdfDriverCreate(drv_object,
97 reg_path,
98 WDF_NO_OBJECT_ATTRIBUTES,
99 &config,
100 &wdf_driver_);
101 ASSERT(NT_SUCCESS(status));
102 if (!NT_SUCCESS(status))
103 return status;
104
105 GoogleDbgPrint("\n>>>>>>>>>> Android USB driver has started >>>>>>>>>>");
106
107 return STATUS_SUCCESS;
108 }
109
110 #pragma code_seg("PAGE")
111
~AndroidUsbDriverObject()112 AndroidUsbDriverObject::~AndroidUsbDriverObject() {
113 ASSERT_IRQL_PASSIVE();
114 }
115
OnAddDevice(PWDFDEVICE_INIT device_init)116 NTSTATUS AndroidUsbDriverObject::OnAddDevice(PWDFDEVICE_INIT device_init) {
117 ASSERT_IRQL_PASSIVE();
118 GoogleDbgPrint("\n++++++++++ AndroidUsbDriverObject::OnAddDevice ++++++++++");
119 // Instantiate our device object extension for this device
120 AndroidUsbDeviceObject* wdf_device_ext =
121 new(NonPagedPool, GANDR_POOL_TAG_KMDF_DEVICE) AndroidUsbDeviceObject();
122 ASSERT(NULL != wdf_device_ext);
123 if (NULL == wdf_device_ext)
124 return STATUS_INSUFFICIENT_RESOURCES;
125
126 // Create and initialize FDO device
127 NTSTATUS status = wdf_device_ext->CreateFDODevice(device_init);
128 ASSERT(NT_SUCCESS(status));
129 if (!NT_SUCCESS(status))
130 delete wdf_device_ext;
131
132 return status;
133 }
134
OnDriverUnload()135 void AndroidUsbDriverObject::OnDriverUnload() {
136 ASSERT_IRQL_PASSIVE();
137 GoogleDbgPrint("\n<<<<<<<<<< Android USB driver is unloaded <<<<<<<<<<");
138 }
139
EvtDeviceAddEntry(WDFDRIVER wdf_drv,PWDFDEVICE_INIT device_init)140 NTSTATUS AndroidUsbDriverObject::EvtDeviceAddEntry(
141 WDFDRIVER wdf_drv,
142 PWDFDEVICE_INIT device_init) {
143 ASSERT_IRQL_PASSIVE();
144 ASSERT((NULL != global_driver_object) && (global_driver_object->wdf_driver() == wdf_drv));
145
146 // Pass it down to our driver object
147 if ((NULL == global_driver_object) ||
148 (global_driver_object->wdf_driver() != wdf_drv)) {
149 return STATUS_INTERNAL_ERROR;
150 }
151
152 return global_driver_object->OnAddDevice(device_init);
153 }
154
EvtDriverUnloadEntry(WDFDRIVER wdf_drv)155 VOID AndroidUsbDriverObject::EvtDriverUnloadEntry(WDFDRIVER wdf_drv) {
156 ASSERT_IRQL_PASSIVE();
157 ASSERT((NULL != global_driver_object) &&
158 (global_driver_object->wdf_driver() == wdf_drv));
159
160 // Pass it down to our driver object
161 if ((NULL != global_driver_object) &&
162 (global_driver_object->wdf_driver() == wdf_drv)) {
163 global_driver_object->OnDriverUnload();
164 // Now we can (and have to) delete our driver object
165 delete global_driver_object;
166 }
167 }
168
169 #if DBG
170
171 #pragma code_seg()
172
GoogleDbgPrint(char * format,...)173 ULONG __cdecl GoogleDbgPrint(char* format, ...) {
174 va_list arg_list;
175 va_start(arg_list, format);
176 ULONG ret =
177 vDbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, format, arg_list);
178 va_end(arg_list);
179
180 return ret;
181 }
182
183 #endif // DBG
184
185 #pragma data_seg()
186 #pragma code_seg()
187