📄 devmgr.c
字号:
/**
* devmgr.c - USB driver stack project for Windows NT 4.0
*
* Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program (in the main directory of the distribution, the file
* COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "usbdriver.h"
#define realloc_buf( pdEV, puRB ) \
{\
PBYTE data_buf;\
int i;\
data_buf = usb_alloc_mem( NonPagedPool, ( pdEV )->desc_buf_size += 1024 );\
RtlZeroMemory( data_buf, ( pdEV )->desc_buf_size );\
for( i = 0; i < ( LONG )( puRB )->context; i++ )\
{\
data_buf[ i ] = ( pdEV )->desc_buf[ i ];\
}\
usb_free_mem( ( pdEV )->desc_buf );\
( pdEV )->desc_buf = data_buf;\
( pdEV )->pusb_dev_desc = ( PUSB_DEVICE_DESC )( pdEV )->desc_buf;\
( puRB )->data_buffer = &data_buf[ ( LONG ) ( puRB )->context ];\
}
//----------------------------------------------------------
USB_DRIVER g_driver_list[DEVMGR_MAX_DRIVERS];
USB_DEV_MANAGER g_dev_mgr;
//----------------------------------------------------------
BOOLEAN
dev_mgr_set_if_driver(PUSB_DEV_MANAGER dev_mgr,
DEV_HANDLE if_handle,
PUSB_DRIVER pdriver,
PUSB_DEV pdev //if pdev != NULL, we use pdev instead if_handle, and must have dev_lock acquired.
)
{
ULONG i;
USE_BASIC_NON_PENDING_IRQL;
if (dev_mgr == NULL || if_handle == 0 || pdriver == NULL)
return FALSE;
i = if_idx_from_handle(if_handle);
if (pdev != NULL)
{
if (dev_state(pdev) < USB_DEV_STATE_BEFORE_ZOMB)
{
pdev->usb_config->interf[i].pif_drv = pdriver;
return TRUE;
}
return FALSE;
}
if (usb_query_and_lock_dev(dev_mgr, if_handle, &pdev) != STATUS_SUCCESS)
return FALSE;
lock_dev(pdev, TRUE);
if (dev_state(pdev) != USB_DEV_STATE_ZOMB)
{
pdev->usb_config->interf[i].pif_drv = pdriver;
}
unlock_dev(pdev, TRUE);
usb_unlock_dev(pdev);
return TRUE;
}
BOOLEAN
dev_mgr_set_driver(PUSB_DEV_MANAGER dev_mgr,
DEV_HANDLE dev_handle,
PUSB_DRIVER pdriver,
PUSB_DEV pdev //if pdev != NULL, we use pdev instead if_handle
)
{
USE_BASIC_NON_PENDING_IRQL;
if (dev_mgr == NULL || dev_handle == 0 || pdriver == NULL)
return FALSE;
if (pdev != NULL)
{
if (dev_state(pdev) < USB_DEV_STATE_BEFORE_ZOMB)
{
pdev->dev_driver = pdriver;
return TRUE;
}
return FALSE;
}
if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) != STATUS_SUCCESS)
return FALSE;
lock_dev(pdev, FALSE);
if (dev_state(pdev) < USB_DEV_STATE_BEFORE_ZOMB)
{
pdev->dev_driver = pdriver;
}
unlock_dev(pdev, FALSE);
usb_unlock_dev(pdev);
return TRUE;
}
BOOLEAN
dev_mgr_post_event(PUSB_DEV_MANAGER dev_mgr, PUSB_EVENT event)
{
KIRQL old_irql;
if (dev_mgr == NULL || event == NULL)
return FALSE;
KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql);
InsertTailList(&dev_mgr->event_list, &event->event_link);
KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE);
return TRUE;
}
VOID
dev_mgr_driver_entry_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdrvr)
{
// Device Info
RtlZeroMemory(pdrvr, sizeof(USB_DRIVER) * DEVMGR_MAX_DRIVERS);
pdrvr[RH_DRIVER_IDX].driver_init = rh_driver_init; // in fact, this routine will init the rh device rather that the driver struct.
pdrvr[RH_DRIVER_IDX].driver_destroy = rh_driver_destroy; // we do not need rh to destroy currently, since that may means fatal hardware failure
pdrvr[HUB_DRIVER_IDX].driver_init = hub_driver_init; //no need, since dev_mgr is also a hub driver
pdrvr[HUB_DRIVER_IDX].driver_destroy = hub_driver_destroy;
pdrvr[UMSS_DRIVER_IDX].driver_init = umss_if_driver_init;
pdrvr[UMSS_DRIVER_IDX].driver_destroy = umss_if_driver_destroy;
pdrvr[COMP_DRIVER_IDX].driver_init = compdev_driver_init;
pdrvr[COMP_DRIVER_IDX].driver_destroy = compdev_driver_destroy;
pdrvr[GEN_DRIVER_IDX].driver_init = gendrv_driver_init;
pdrvr[GEN_DRIVER_IDX].driver_destroy = gendrv_driver_destroy;
pdrvr[GEN_IF_DRIVER_IDX].driver_init = gendrv_if_driver_init;
pdrvr[GEN_IF_DRIVER_IDX].driver_destroy = gendrv_if_driver_destroy;
pdrvr[MOUSE_DRIVER_IDX].driver_init = mouse_driver_init;
pdrvr[MOUSE_DRIVER_IDX].driver_destroy = mouse_driver_destroy;
//pdrvr[KEYBOARD_DRIVER_IDX].driver_init = gendrv_if_driver_init;
//pdrvr[KEYBOARD_DRIVER_IDX].driver_destroy = gendrv_if_driver_destroy;
}
BOOLEAN
dev_mgr_strobe(PUSB_DEV_MANAGER dev_mgr)
{
PUSB_EVENT pevent;
HANDLE thread_handle;
if (dev_mgr == NULL)
return FALSE;
if (dev_mgr->hcd_count == 0)
return FALSE;
dev_mgr->term_flag = FALSE;
if (dev_mgr->hcd_count == 0)
return FALSE;
KeInitializeSpinLock(&dev_mgr->event_list_lock);
InitializeListHead(&dev_mgr->event_list);
init_event_pool(&dev_mgr->event_pool);
pevent = alloc_event(&dev_mgr->event_pool, 1);
if (pevent == NULL)
{
destroy_event_pool(&dev_mgr->event_pool);
return FALSE;
}
pevent->flags = USB_EVENT_FLAG_ACTIVE;
pevent->event = USB_EVENT_INIT_DEV_MGR;
pevent->process_queue = event_list_default_process_queue;
pevent->process_event = (PROCESS_EVENT)dev_mgr_event_init;
pevent->context = (ULONG) dev_mgr;
KeInitializeEvent(&dev_mgr->wake_up_event, SynchronizationEvent, FALSE);
InsertTailList(&dev_mgr->event_list, &pevent->event_link);
if (PsCreateSystemThread(&thread_handle, 0, NULL, NULL, NULL, dev_mgr_thread, dev_mgr) != STATUS_SUCCESS)
{
destroy_event_pool(&dev_mgr->event_pool);
return FALSE;
}
ObReferenceObjectByHandle(thread_handle,
THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID *) & dev_mgr->pthread, NULL);
ZwClose(thread_handle);
return TRUE;
}
BOOLEAN
dev_mgr_event_init(PUSB_DEV pdev, //always null. we do not use this param
ULONG event, ULONG context, ULONG param)
{
LARGE_INTEGER due_time;
PUSB_DEV_MANAGER dev_mgr;
LONG i;
usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_event_init(): dev_mgr=0x%x, event=0x%x\n", context, event));
dev_mgr = (PUSB_DEV_MANAGER) context;
if (dev_mgr == NULL)
return FALSE;
if (event != USB_EVENT_INIT_DEV_MGR)
return FALSE;
//dev_mgr->root_hub = NULL;
KeInitializeTimer(&dev_mgr->dev_mgr_timer);
KeInitializeDpc(&dev_mgr->dev_mgr_timer_dpc, dev_mgr_timer_dpc_callback, (PVOID) dev_mgr);
KeInitializeSpinLock(&dev_mgr->timer_svc_list_lock);
InitializeListHead(&dev_mgr->timer_svc_list);
init_timer_svc_pool(&dev_mgr->timer_svc_pool);
dev_mgr->timer_click = 0;
init_irp_list(&dev_mgr->irp_list);
KeInitializeSpinLock(&dev_mgr->dev_list_lock);
InitializeListHead(&dev_mgr->dev_list);
dev_mgr->hub_count = 0;
InitializeListHead(&dev_mgr->hub_list);
dev_mgr->conn_count = 0;
dev_mgr->driver_list = g_driver_list;
dev_mgr_driver_entry_init(dev_mgr, dev_mgr->driver_list);
for(i = 0; i < DEVMGR_MAX_DRIVERS; i++)
{
if (dev_mgr->driver_list[i].driver_init == NULL)
continue;
if (dev_mgr->driver_list[i].driver_init(dev_mgr, &dev_mgr->driver_list[i]) == FALSE)
break;
}
if (i == DEVMGR_MAX_DRIVERS)
{
due_time.QuadPart = -(DEV_MGR_TIMER_INTERVAL_NS - 10);
KeSetTimerEx(&dev_mgr->dev_mgr_timer,
due_time, DEV_MGR_TIMER_INTERVAL_MS, &dev_mgr->dev_mgr_timer_dpc);
return TRUE;
}
i--;
for(; i >= 0; i--)
{
if (dev_mgr->driver_list[i].driver_destroy)
dev_mgr->driver_list[i].driver_destroy(dev_mgr, &dev_mgr->driver_list[i]);
}
KeCancelTimer(&dev_mgr->dev_mgr_timer);
KeRemoveQueueDpc(&dev_mgr->dev_mgr_timer_dpc);
return FALSE;
}
VOID
dev_mgr_destroy(PUSB_DEV_MANAGER dev_mgr)
{
LONG i;
// oops...
KeCancelTimer(&dev_mgr->dev_mgr_timer);
KeRemoveQueueDpc(&dev_mgr->dev_mgr_timer_dpc);
for(i = DEVMGR_MAX_DRIVERS - 1; i >= 0; i--)
dev_mgr->driver_list[i].driver_destroy(dev_mgr, &dev_mgr->driver_list[i]);
destroy_irp_list(&dev_mgr->irp_list);
destroy_timer_svc_pool(&dev_mgr->timer_svc_pool);
destroy_event_pool(&dev_mgr->event_pool);
}
VOID
NTAPI
dev_mgr_thread(PVOID context)
{
PUSB_DEV_MANAGER dev_mgr;
PUSB_EVENT pevent;
PLIST_ENTRY pthis, pnext;
USB_EVENT usb_event;
LARGE_INTEGER time_out;
NTSTATUS status;
BOOLEAN dev_mgr_inited;
KIRQL old_irql;
LONG i;
dev_mgr = (PUSB_DEV_MANAGER) context;
dev_mgr_inited = FALSE;
usb_cal_cpu_freq();
time_out.u.LowPart = (10 * 1000 * 1000) * 100 - 1; //1 minutes
time_out.u.HighPart = 0;
time_out.QuadPart = -time_out.QuadPart;
//usb_dbg_print( DBGLVL_MAXIMUM + 1, ( "dev_mgr_thread(): current uhci status=0x%x\n", uhci_status( dev_mgr->pdev_ext->uhci ) ) );
while (dev_mgr->term_flag == FALSE)
{
KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql);
if (IsListEmpty(&dev_mgr->event_list) == TRUE)
{
KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
status = KeWaitForSingleObject(&dev_mgr->wake_up_event, Executive, KernelMode, TRUE, &time_out);
continue;
}
/*
usb_dbg_print( DBGLVL_MAXIMUM, ( "dev_mgr_thread(): current element in event list is 0x%x\n", \
dbg_count_list( &dev_mgr->event_list ) ) ); */
dev_mgr_inited = TRUE; //since we have post one event, if this statement is executed, dev_mgr_event_init must be called sometime later or earlier
ListFirst(&dev_mgr->event_list, pthis);
pevent = struct_ptr(pthis, USB_EVENT, event_link);
while (pevent && ((pevent->flags & USB_EVENT_FLAG_ACTIVE) == 0))
{
//skip inactive ones
ListNext(&dev_mgr->event_list, &pevent->event_link, pnext);
pevent = struct_ptr(pnext, USB_EVENT, event_link);
}
if (pevent != NULL)
{
if (pevent->process_queue == NULL)
pevent->process_queue = event_list_default_process_queue;
pevent->process_queue(&dev_mgr->event_list, &dev_mgr->event_pool, pevent, &usb_event);
}
else
{
//no active event
KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
status = KeWaitForSingleObject(&dev_mgr->wake_up_event, Executive, KernelMode, TRUE, &time_out // 10 minutes
);
usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_thread(): wake up, reason=0x%x\n", status));
continue;
}
KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
if (usb_event.process_event)
{
usb_event.process_event(usb_event.pdev, usb_event.event, usb_event.context, usb_event.param);
}
else
{
event_list_default_process_event(usb_event.pdev,
usb_event.event, usb_event.context, usb_event.param);
}
}
if (dev_mgr_inited)
{
for(i = 0; i < dev_mgr->hcd_count; i++)
dev_mgr_disconnect_dev(dev_mgr->hcd_array[i]->hcd_get_root_hub(dev_mgr->hcd_array[i]));
dev_mgr_destroy(dev_mgr);
}
PsTerminateSystemThread(0);
}
VOID
NTAPI
dev_mgr_timer_dpc_callback(PKDPC Dpc, PVOID context, PVOID SystemArgument1, PVOID SystemArgument2)
{
PUSB_DEV_MANAGER dev_mgr;
LIST_HEAD templist;
PLIST_ENTRY pthis, pnext;
static ULONG ticks = 0;
ticks++;
dev_mgr = (PUSB_DEV_MANAGER) context;
if (dev_mgr == NULL)
return;
dev_mgr->timer_click++;
InitializeListHead(&templist);
KeAcquireSpinLockAtDpcLevel(&dev_mgr->timer_svc_list_lock);
if (IsListEmpty(&dev_mgr->timer_svc_list) == TRUE)
{
KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock);
return;
}
ListFirst(&dev_mgr->timer_svc_list, pthis);
while (pthis)
{
((PTIMER_SVC) pthis)->counter++;
ListNext(&dev_mgr->timer_svc_list, pthis, pnext);
if (((PTIMER_SVC) pthis)->counter >= ((PTIMER_SVC) pthis)->threshold)
{
RemoveEntryList(pthis);
InsertTailList(&templist, pthis);
}
pthis = pnext;
}
KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock);
while (IsListEmpty(&templist) == FALSE)
{
pthis = RemoveHeadList(&templist);
((PTIMER_SVC) pthis)->func(((PTIMER_SVC) pthis)->pdev, (PVOID) ((PTIMER_SVC) pthis)->context);
KeAcquireSpinLockAtDpcLevel(&dev_mgr->timer_svc_list_lock);
free_timer_svc(&dev_mgr->timer_svc_pool, (PTIMER_SVC) pthis);
KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock);
}
}
BOOLEAN
dev_mgr_request_timer_svc(PUSB_DEV_MANAGER dev_mgr,
PUSB_DEV pdev, ULONG context, ULONG due_time, TIMER_SVC_HANDLER handler)
{
PTIMER_SVC timer_svc;
KIRQL old_irql;
if (dev_mgr == NULL || pdev == NULL || due_time == 0 || handler == NULL)
return FALSE;
KeAcquireSpinLock(&dev_mgr->timer_svc_list_lock, &old_irql);
timer_svc = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1);
if (timer_svc == NULL)
{
KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
return FALSE;
}
timer_svc->pdev = pdev;
timer_svc->threshold = due_time;
timer_svc->func = handler;
timer_svc->counter = 0;
InsertTailList(&dev_mgr->timer_svc_list, &timer_svc->timer_svc_link);
KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
return TRUE;
}
BYTE
dev_mgr_alloc_addr(PUSB_DEV_MANAGER dev_mgr, PHCD hcd)
{
// alloc a usb addr for the device within 1-128
if (dev_mgr == NULL || hcd == NULL)
return 0xff;
return hcd->hcd_alloc_addr(hcd);
}
BOOLEAN
dev_mgr_free_addr(PUSB_DEV_MANAGER dev_mgr, PUSB_DEV pdev, BYTE addr)
{
PHCD hcd;
if (addr & 0x80)
return FALSE;
if (dev_mgr == NULL || pdev == NULL)
return FALSE;
hcd = pdev->hcd;
if (hcd == NULL)
return FALSE;
hcd->hcd_free_addr(hcd, addr);
return TRUE;
}
PUSB_DEV
dev_mgr_alloc_device(PUSB_DEV_MANAGER dev_mgr, PHCD hcd)
{
BYTE addr;
PUSB_DEV pdev;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -