/* * 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()