187 lines
5.7 KiB
C++
187 lines
5.7 KiB
C++
/*
|
|
* Copyright (C) 2006 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/** \file
|
|
This file consists of implementation of class AndroidUsbDriverObject that
|
|
encapsulates our driver object
|
|
*/
|
|
#pragma data_seg()
|
|
#pragma code_seg()
|
|
|
|
#include "precomp.h"
|
|
#include "android_usb_device_object.h"
|
|
#include "android_usb_driver_object.h"
|
|
|
|
#pragma data_seg()
|
|
|
|
/** Globally accessible instance of the AndroidUsbDriverObject.
|
|
NT OS design allows us using of a global pointer to our driver object
|
|
instance since it can't be created or destroyed concurently and its value
|
|
is not going to change between creation and destruction.
|
|
*/
|
|
AndroidUsbDriverObject* global_driver_object = NULL;
|
|
|
|
#pragma code_seg("INIT")
|
|
|
|
extern "C" {
|
|
|
|
/// Main entry point to the driver
|
|
NTSTATUS DriverEntry(PDRIVER_OBJECT drv_object, PUNICODE_STRING reg_path) {
|
|
// Just pass it down inside the class
|
|
return AndroidUsbDriverObject::DriverEntry(drv_object, reg_path);
|
|
}
|
|
|
|
} // extern "C"
|
|
|
|
NTSTATUS AndroidUsbDriverObject::DriverEntry(PDRIVER_OBJECT drv_object,
|
|
PUNICODE_STRING reg_path) {
|
|
ASSERT_IRQL_PASSIVE();
|
|
ASSERT(NULL != drv_object);
|
|
ASSERT((NULL != reg_path) &&
|
|
(NULL != reg_path->Buffer) &&
|
|
(0 != reg_path->Length));
|
|
|
|
// Instantiate driver object
|
|
global_driver_object = new(NonPagedPool, GANDR_POOL_TAG_DRIVER_OBJECT)
|
|
AndroidUsbDriverObject(drv_object, reg_path);
|
|
ASSERT(NULL != global_driver_object);
|
|
if (NULL == global_driver_object)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
// Initialize driver object
|
|
NTSTATUS status = global_driver_object->OnDriverEntry(drv_object, reg_path);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
// Something went wrong. Delete our driver object and get out of here.
|
|
delete global_driver_object;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
AndroidUsbDriverObject::AndroidUsbDriverObject(PDRIVER_OBJECT drv_object,
|
|
PUNICODE_STRING reg_path)
|
|
: driver_object_(drv_object),
|
|
wdf_driver_(NULL) {
|
|
ASSERT_IRQL_PASSIVE();
|
|
ASSERT(NULL != driver_object());
|
|
}
|
|
|
|
NTSTATUS AndroidUsbDriverObject::OnDriverEntry(PDRIVER_OBJECT drv_object,
|
|
PUNICODE_STRING reg_path) {
|
|
ASSERT_IRQL_PASSIVE();
|
|
ASSERT(driver_object() == drv_object);
|
|
|
|
// Initiialize driver config, specifying our unload callback and default
|
|
// pool tag for memory allocations that KMDF does on our behalf.
|
|
WDF_DRIVER_CONFIG config;
|
|
WDF_DRIVER_CONFIG_INIT(&config, EvtDeviceAddEntry);
|
|
config.EvtDriverUnload = EvtDriverUnloadEntry;
|
|
config.DriverPoolTag = GANDR_POOL_TAG_DEFAULT;
|
|
|
|
// Create a framework driver object to represent our driver.
|
|
NTSTATUS status = WdfDriverCreate(drv_object,
|
|
reg_path,
|
|
WDF_NO_OBJECT_ATTRIBUTES,
|
|
&config,
|
|
&wdf_driver_);
|
|
ASSERT(NT_SUCCESS(status));
|
|
if (!NT_SUCCESS(status))
|
|
return status;
|
|
|
|
GoogleDbgPrint("\n>>>>>>>>>> Android USB driver has started >>>>>>>>>>");
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
#pragma code_seg("PAGE")
|
|
|
|
AndroidUsbDriverObject::~AndroidUsbDriverObject() {
|
|
ASSERT_IRQL_PASSIVE();
|
|
}
|
|
|
|
NTSTATUS AndroidUsbDriverObject::OnAddDevice(PWDFDEVICE_INIT device_init) {
|
|
ASSERT_IRQL_PASSIVE();
|
|
GoogleDbgPrint("\n++++++++++ AndroidUsbDriverObject::OnAddDevice ++++++++++");
|
|
// Instantiate our device object extension for this device
|
|
AndroidUsbDeviceObject* wdf_device_ext =
|
|
new(NonPagedPool, GANDR_POOL_TAG_KMDF_DEVICE) AndroidUsbDeviceObject();
|
|
ASSERT(NULL != wdf_device_ext);
|
|
if (NULL == wdf_device_ext)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
// Create and initialize FDO device
|
|
NTSTATUS status = wdf_device_ext->CreateFDODevice(device_init);
|
|
ASSERT(NT_SUCCESS(status));
|
|
if (!NT_SUCCESS(status))
|
|
delete wdf_device_ext;
|
|
|
|
return status;
|
|
}
|
|
|
|
void AndroidUsbDriverObject::OnDriverUnload() {
|
|
ASSERT_IRQL_PASSIVE();
|
|
GoogleDbgPrint("\n<<<<<<<<<< Android USB driver is unloaded <<<<<<<<<<");
|
|
}
|
|
|
|
NTSTATUS AndroidUsbDriverObject::EvtDeviceAddEntry(
|
|
WDFDRIVER wdf_drv,
|
|
PWDFDEVICE_INIT device_init) {
|
|
ASSERT_IRQL_PASSIVE();
|
|
ASSERT((NULL != global_driver_object) && (global_driver_object->wdf_driver() == wdf_drv));
|
|
|
|
// Pass it down to our driver object
|
|
if ((NULL == global_driver_object) ||
|
|
(global_driver_object->wdf_driver() != wdf_drv)) {
|
|
return STATUS_INTERNAL_ERROR;
|
|
}
|
|
|
|
return global_driver_object->OnAddDevice(device_init);
|
|
}
|
|
|
|
VOID AndroidUsbDriverObject::EvtDriverUnloadEntry(WDFDRIVER wdf_drv) {
|
|
ASSERT_IRQL_PASSIVE();
|
|
ASSERT((NULL != global_driver_object) &&
|
|
(global_driver_object->wdf_driver() == wdf_drv));
|
|
|
|
// Pass it down to our driver object
|
|
if ((NULL != global_driver_object) &&
|
|
(global_driver_object->wdf_driver() == wdf_drv)) {
|
|
global_driver_object->OnDriverUnload();
|
|
// Now we can (and have to) delete our driver object
|
|
delete global_driver_object;
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
|
|
#pragma code_seg()
|
|
|
|
ULONG __cdecl GoogleDbgPrint(char* format, ...) {
|
|
va_list arg_list;
|
|
va_start(arg_list, format);
|
|
ULONG ret =
|
|
vDbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, format, arg_list);
|
|
va_end(arg_list);
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif // DBG
|
|
|
|
#pragma data_seg()
|
|
#pragma code_seg()
|