umss.c
来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 1,933 行 · 第 1/5 页
C
1,933 行
{
PURB purb;
NTSTATUS status;
PUSB_CTRL_SETUP_PACKET psetup;
PUSB_DEV_MANAGER dev_mgr;
PUSB_DRIVER pdrvr;
usb_dbg_print(DBGLVL_MAXIMUM, ("umss_connect(): entering...\n"));
dev_mgr = param->dev_mgr;
pdrvr = param->pdriver;
//directly set the configuration
purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
if (purb == NULL)
return FALSE;
psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
urb_init((purb));
purb->endp_handle = dev_handle | 0xffff;
purb->data_buffer = NULL;
purb->data_length = 0;
purb->completion = umss_set_cfg_completion;
purb->context = dev_mgr;
purb->reference = (LONG) pdrvr;
psetup->bmRequestType = 0;
psetup->bRequest = USB_REQ_SET_CONFIGURATION;
psetup->wValue = 1;
psetup->wIndex = 0;
psetup->wLength = 0;
status = usb_submit_urb(dev_mgr, purb);
if (status != STATUS_PENDING)
{
usb_free_mem(purb);
return FALSE;
}
return TRUE;
}
VOID
umss_set_cfg_completion(PURB purb, PVOID pcontext)
{
PUSB_CTRL_SETUP_PACKET psetup;
PUCHAR buf;
PWORK_QUEUE_ITEM pwork_item;
PUMSS_CREATE_DATA pcd;
DEV_HANDLE dev_handle;
NTSTATUS status;
PUSB_DEV_MANAGER dev_mgr;
PUSB_DRIVER pdrvr;
if (purb == NULL || pcontext == NULL)
return;
dev_mgr = (PUSB_DEV_MANAGER) pcontext;
pdrvr = (PUSB_DRIVER) purb->reference;
dev_handle = purb->endp_handle & ~0xffff;
if (purb->status != STATUS_SUCCESS)
{
usb_free_mem(purb);
return;
}
buf = usb_alloc_mem(NonPagedPool, 512);
if (buf == NULL)
{
usb_free_mem(purb);
return;
}
//now let's get the descs, one configuration, one interface and two endpoint
psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
purb->data_buffer = buf;
purb->data_length = 512;
purb->completion = NULL; //this is an immediate request, no needs completion
purb->context = dev_mgr;
purb->reference = 0;
psetup->bmRequestType = 0x80;
psetup->bRequest = USB_REQ_GET_DESCRIPTOR;
psetup->wValue = USB_DT_CONFIG << 8;
psetup->wIndex = 0;
psetup->wLength = 512;
status = usb_submit_urb(dev_mgr, purb);
if (status == STATUS_PENDING)
{
TRAP();
}
usb_free_mem(purb);
purb = NULL;
if (status != STATUS_SUCCESS)
{
usb_free_mem(buf);
buf = NULL;
return;
}
pcd = usb_alloc_mem(NonPagedPool, sizeof(WORK_QUEUE_ITEM) + sizeof(UMSS_CREATE_DATA));
if (pcd == NULL)
{
usb_free_mem(buf);
buf = NULL;
return;
}
pcd->desc_buf = buf;
pcd->dev_handle = dev_handle;
pcd->dev_mgr = dev_mgr;
pcd->pdriver = pdrvr;
pwork_item = (PWORK_QUEUE_ITEM) (&pcd[1]);
ExInitializeWorkItem(pwork_item, umss_start_create_device, (PVOID) pcd);
ExQueueWorkItem(pwork_item, DelayedWorkQueue);
}
VOID NTAPI
umss_start_create_device(IN PVOID Parameter)
{
LONG i;
PUCHAR desc_buf;
NTSTATUS status;
PUSB_DEV pdev;
DEV_HANDLE dev_handle;
PUSB_DRIVER pdrvr;
PDEVICE_OBJECT pdev_obj;
PUSB_DEV_MANAGER dev_mgr;
PUMSS_CREATE_DATA pcd;
PUSB_INTERFACE_DESC pif_desc;
PUSB_ENDPOINT_DESC pendp_desc;
PUMSS_DEVICE_EXTENSION pdev_ext;
PUSB_CONFIGURATION_DESC pconfig_desc;
USE_BASIC_NON_PENDING_IRQL;
if (Parameter == NULL)
return;
pcd = (PUMSS_CREATE_DATA) Parameter;
desc_buf = pcd->desc_buf;
dev_mgr = pcd->dev_mgr;
dev_handle = pcd->dev_handle;
pdrvr = pcd->pdriver;
usb_free_mem(pcd);
pcd = NULL;
status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
if (status != STATUS_SUCCESS)
{
usb_free_mem(desc_buf);
return;
}
pdev_obj = umss_create_device(dev_mgr, pdrvr, dev_handle, FALSE);
lock_dev(pdev, FALSE);
if (pdev_obj == NULL ||
dev_state(pdev) == USB_DEV_STATE_ZOMB ||
dev_mgr_set_driver(dev_mgr, dev_handle, pdrvr, pdev) == FALSE)
{
usb_free_mem(desc_buf);
unlock_dev(pdev, FALSE);
if (pdev_obj)
umss_delete_device(dev_mgr, pdrvr, pdev_obj, FALSE);
usb_unlock_dev(pdev);
return;
}
unlock_dev(pdev, FALSE);
pdev_ext = (PUMSS_DEVICE_EXTENSION) pdev_obj->DeviceExtension;
pdev_ext->desc_buf = desc_buf;
pdev_ext->pif_desc = NULL;
pdev_ext->pin_endp_desc = pdev_ext->pout_endp_desc = NULL;
pconfig_desc = (PUSB_CONFIGURATION_DESC) desc_buf;
pif_desc = (PUSB_INTERFACE_DESC) (&pconfig_desc[1]);
//search for our if
for(i = 0; ((UCHAR) i) < pconfig_desc->bNumInterfaces; i++)
{
if (pif_desc->bLength == sizeof(USB_INTERFACE_DESC) && pif_desc->bDescriptorType == USB_DT_INTERFACE)
{
if (pif_desc->bInterfaceClass == USB_CLASS_MASS_STORAGE)
{
pdev_ext->pif_desc = pif_desc;
pdev_ext->if_idx = (UCHAR) i;
break;
}
else
{
if (usb_skip_if_and_altif((PUCHAR *) & pif_desc) == FALSE)
break;
}
}
else
{
break;
}
}
if (pdev_ext->pif_desc)
{
pendp_desc = (PUSB_ENDPOINT_DESC) & pif_desc[1];
for(i = 0; ((UCHAR) i) < pif_desc->bNumEndpoints; i++)
{
if (pendp_desc->bDescriptorType == USB_DT_ENDPOINT
&& pendp_desc->bLength == sizeof(USB_ENDPOINT_DESC))
{
if ((pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
{
pdev_ext->pint_endp_desc = pendp_desc;
pdev_ext->int_endp_idx = (UCHAR) i;
}
else if ((pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
{
if (pendp_desc->bEndpointAddress & USB_DIR_IN)
{
pdev_ext->pin_endp_desc = pendp_desc;
pdev_ext->in_endp_idx = (UCHAR) i;
}
else
{
pdev_ext->pout_endp_desc = pendp_desc;
pdev_ext->out_endp_idx = (UCHAR) i;
}
}
pendp_desc = &pendp_desc[1];
}
else
break;
}
}
usb_unlock_dev(pdev);
return;
}
BOOLEAN
umss_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
UNREFERENCED_PARAMETER(dev_handle);
UNREFERENCED_PARAMETER(dev_mgr);
return TRUE;
}
BOOLEAN
umss_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
PDEVICE_OBJECT dev_obj;
NTSTATUS status;
PUSB_DEV pdev;
PUSB_DRIVER pdrvr;
if (dev_mgr == NULL || dev_handle == 0)
return FALSE;
pdev = NULL;
//special use of the lock dev, simply use this routine to get the dev
status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
if (pdev == NULL)
{
return FALSE;
}
if (status == STATUS_SUCCESS)
{
// must be a bug
TRAP();
usb_unlock_dev(pdev);
}
pdrvr = pdev->dev_driver;
dev_obj = pdev->dev_obj;
pdev = NULL;
return umss_delete_device(dev_mgr, pdrvr, dev_obj, FALSE);
}
VOID
umss_deferred_delete_device(PVOID context)
{
PDEVICE_OBJECT dev_obj;
PUMSS_DEVICE_EXTENSION pdev_ext;
PUMSS_DRVR_EXTENSION pdrvr_ext;
LARGE_INTEGER interval;
if (context == NULL)
return;
dev_obj = (PDEVICE_OBJECT) context;
pdev_ext = dev_obj->DeviceExtension;
pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext;
interval.QuadPart = -20000; //two ms
for(;;)
{
if (dev_obj->ReferenceCount)
KeDelayExecutionThread(KernelMode, TRUE, &interval);
else
{
KeDelayExecutionThread(KernelMode, TRUE, &interval);
if (dev_obj->ReferenceCount == 0)
break;
}
}
usb_dbg_print(DBGLVL_MAXIMUM, ("umss_deferred_delete_device(): delete device, 0x%x\n", dev_obj));
ExAcquireFastMutex(&pdrvr_ext->dev_list_mutex);
RemoveEntryList(&pdev_ext->dev_obj_link);
pdrvr_ext->dev_count--;
ExReleaseFastMutex(&pdrvr_ext->dev_list_mutex);
IoDeleteDevice(dev_obj);
return;
}
BOOLEAN
umss_delete_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdrvr, PDEVICE_OBJECT dev_obj, BOOLEAN is_if)
{
CHAR dev_name[64];
STRING string;
UNICODE_STRING symb_link;
PUMSS_DEVICE_EXTENSION pdev_ext;
PUMSS_DRVR_EXTENSION pdrvr_ext;
if (dev_obj == NULL)
return FALSE;
if (pdrvr == NULL || dev_mgr == NULL)
return FALSE;
pdev_ext = (PUMSS_DEVICE_EXTENSION) dev_obj->DeviceExtension;
pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext;
if (is_if == FALSE)
sprintf(dev_name, "\\DosDevices\\umssdev%d", (int)pdev_ext->umss_dev_id);
else
sprintf(dev_name, "\\DosDevices\\umssifdev%d", (int)pdev_ext->umss_dev_id);
RtlInitString(&string, dev_name);
RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
IoDeleteSymbolicLink(&symb_link);
RtlFreeUnicodeString(&symb_link);
if (pdev_ext->desc_buf)
{
usb_dbg_print(DBGLVL_MAXIMUM, ("umss_delete_device(): delete desc_buf\n"));
usb_free_mem(pdev_ext->desc_buf);
pdev_ext->desc_buf = NULL;
}
if (dev_obj->ReferenceCount == 0)
{
ExAcquireFastMutex(&pdrvr_ext->dev_list_mutex);
RemoveEntryList(&pdev_ext->dev_obj_link);
pdrvr_ext->dev_count--;
ExReleaseFastMutex(&pdrvr_ext->dev_list_mutex);
IoDeleteDevice(dev_obj);
return TRUE;
}
//
// FIXME: how if the driver unloading happens
// since this is called in dev_mgr_disconnect_dev, umss_schedule_workitem
// can not protect the USB_DEV object from be deleted. so the workitem
// can not access anything relative to the USB_DEV object. In this case
// we will tollerate the usb_query_and_lock_dev failure since it will
// never success when come to this point, and we won't pass dev_mgr
// and pdev to the function. But other scenarios, usb_query_and_lock_dev
// can not fail if dev_mgr and pdev are passed valid.
// When driver is unloading, don't know. Wish NT will unload the driver
// only when all the devices to the driver are deleted.
//
umss_schedule_workitem(dev_obj, umss_deferred_delete_device, NULL, 0);
return TRUE;
}
VOID
umss_submit_io_packet(PDEVICE_OBJECT dev_obj, PIO_PACKET io_packet)
{
NTSTATUS status;
PUMSS_DEVICE_EXTENSION pdev_ext;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?