umss.c
来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 1,933 行 · 第 1/5 页
C
1,933 行
status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev);
if (status != STATUS_SUCCESS)
{
goto ERROR_OUT;
}
#ifdef _TIANSHENG_DRIVER
if (!((pdev->pusb_dev_desc->idVendor == 0x03eb && pdev->pusb_dev_desc->idProduct == 0x2002)
|| (pdev->pusb_dev_desc->idVendor == 0x0ea0 && pdev->pusb_dev_desc->idProduct == 0x6803)
|| (pdev->pusb_dev_desc->idVendor == 0x0ef5 && pdev->pusb_dev_desc->idProduct == 0x2202)))
{
// check TianSheng's product
goto ERROR_OUT;
}
#endif
pdev_obj = umss_create_device(dev_mgr, pdrvr, if_handle, TRUE);
if (pdev_obj == NULL)
{
goto ERROR_OUT;
}
lock_dev(pdev, FALSE);
if (dev_state(pdev) == USB_DEV_STATE_ZOMB ||
dev_mgr_set_if_driver(dev_mgr, if_handle, pdrvr, pdev) == FALSE)
{
unlock_dev(pdev, FALSE);
if (pdev_obj)
{
umss_delete_device(dev_mgr, pdrvr, pdev_obj, TRUE);
}
goto ERROR_OUT;
}
if (pdev->usb_config)
{
pdev->usb_config->interf[if_idx].if_ext = pdev_obj;
pdev->usb_config->interf[if_idx].if_ext_size = 0;
}
// olympus dev needs special care
if (UMSS_OLYMPUS_VENDOR_ID == pdev->pusb_dev_desc->idVendor)
status = TRUE;
else
status = FALSE;
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]);
if (status)
pdev_ext->flags |= UMSS_DEV_FLAG_OLYMPUS_DEV;
//search for our if
for(i = 0; ((UCHAR) i) < if_idx; i++)
{
if (usb_skip_if_and_altif((PUCHAR *) & pif_desc) == FALSE)
break;
}
pdev_ext->pif_desc = pif_desc;
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;
}
}
// notify the class driver, some device comes
pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext;
if (pdrvr_ext && pdrvr_ext->class_driver_info.add_device && pdrvr_ext->class_driver_info.fdo_driver)
pdrvr_ext->class_driver_info.add_device(pdrvr_ext->class_driver_info.fdo_driver, pdev_obj);
usb_unlock_dev(pdev);
return TRUE;
ERROR_OUT:
if (desc_buf)
usb_free_mem(desc_buf);
if (purb)
usb_free_mem(purb);
usb_unlock_dev(pdev);
desc_buf = NULL;
purb = NULL;
return FALSE;
}
BOOLEAN
umss_if_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle)
{
LONG if_idx;
NTSTATUS status;
PUSB_DEV pdev;
PUSB_DRIVER pdrvr = NULL;
PDEVICE_OBJECT dev_obj = NULL;
PUMSS_DRVR_EXTENSION pdrvr_ext;
PUMSS_DEVICE_EXTENSION pdev_ext;
if (dev_mgr == NULL || if_handle == 0)
return FALSE;
pdev = NULL;
if_idx = if_idx_from_handle(if_handle);
//
// special use of the lock dev, simply use this routine to get the dev
//
status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev);
if (pdev == NULL)
{
return FALSE;
}
if (status == STATUS_SUCCESS)
{
// must be a bug
TRAP();
}
if (pdev->usb_config)
{
pdrvr = pdev->usb_config->interf[if_idx].pif_drv;
dev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext;
}
pdev = NULL;
// notify the class driver, some device gone
pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext;
pdev_ext = dev_obj->DeviceExtension;
if (pdrvr_ext && pdrvr_ext->class_driver_info.pnp_dispatch)
pdrvr_ext->class_driver_info.pnp_dispatch(dev_obj, UMSS_PNPMSG_DISCONNECT, NULL);
// no need to unlock the dev
return umss_delete_device(dev_mgr, pdrvr, dev_obj, TRUE);
}
BOOLEAN
umss_if_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle)
{
LONG if_idx;
NTSTATUS status;
PUSB_DEV pdev;
PUSB_DRIVER pdrvr = NULL;
PDEVICE_OBJECT dev_obj = NULL;
PUMSS_DRVR_EXTENSION pdrvr_ext;
PUMSS_DEVICE_EXTENSION pdev_ext;
USE_BASIC_NON_PENDING_IRQL;
if (dev_mgr == NULL || if_handle == 0)
return FALSE;
pdev = NULL;
if_idx = if_idx_from_handle(if_handle);
// special use of the lock dev, simply use this routine to get the dev
status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev);
if (status != STATUS_SUCCESS)
{
return FALSE;
}
lock_dev(pdev, FALSE);
if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
{
return FALSE;
}
if (pdev->usb_config)
{
pdrvr = pdev->usb_config->interf[if_idx].pif_drv;
dev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext;
}
unlock_dev(pdev, FALSE);
// notify the class driver, some device stops
pdev_ext = dev_obj->DeviceExtension;
pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext;
if (pdrvr_ext && pdrvr_ext->class_driver_info.pnp_dispatch)
pdrvr_ext->class_driver_info.pnp_dispatch(dev_obj, UMSS_PNPMSG_STOP, NULL);
usb_unlock_dev(pdev);
return TRUE;
}
VOID
umss_load_class_driver(PVOID context)
{
NTSTATUS status;
UNICODE_STRING unicode_string;
UNREFERENCED_PARAMETER(context);
//
// let's load the class driver
//
RtlInitUnicodeString(&unicode_string,
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\usbstor");
status = ZwLoadDriver(&unicode_string);
usb_dbg_print(DBGLVL_MAXIMUM,
("umss_load_class_driver(): try to load class driver, status=0x%x\n", status));
}
BOOLEAN
umss_if_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
PUMSS_DRVR_EXTENSION pdrvr_ext;
if (dev_mgr == NULL || pdriver == NULL)
return FALSE;
//init driver structure, no PNP table functions
pdriver->driver_desc.flags = USB_DRIVER_FLAG_IF_CAPABLE;
pdriver->driver_desc.vendor_id = 0x0000; // USB Vendor ID
pdriver->driver_desc.product_id = 0x0000; // USB Product ID.
pdriver->driver_desc.release_num = 0x100; // Release Number of Device
pdriver->driver_desc.config_val = 1; // Configuration Value
pdriver->driver_desc.if_num = 1; // Interface Number
pdriver->driver_desc.if_class = USB_CLASS_MASS_STORAGE; // Interface Class
pdriver->driver_desc.if_sub_class = 0; // Interface SubClass
pdriver->driver_desc.if_protocol = 0; // Interface Protocol
pdriver->driver_desc.driver_name = "USB Mass Storage interface driver"; // Driver name for Name Registry
pdriver->driver_desc.dev_class = USB_CLASS_PER_INTERFACE;
pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(UMSS_DRVR_EXTENSION));
pdriver->driver_ext_size = sizeof(UMSS_DRVR_EXTENSION);
RtlZeroMemory(pdriver->driver_ext, sizeof(UMSS_DRVR_EXTENSION));
pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdriver->driver_ext;
pdrvr_ext->dev_count = 0;
InitializeListHead(&pdrvr_ext->dev_list);
ExInitializeFastMutex(&pdrvr_ext->dev_list_mutex);
pdriver->disp_tbl.version = 1;
pdriver->disp_tbl.dev_connect = umss_if_connect;
pdriver->disp_tbl.dev_disconnect = umss_if_disconnect;
pdriver->disp_tbl.dev_stop = umss_if_stop;
pdriver->disp_tbl.dev_reserved = NULL;
if ((pdrvr_ext->port_dev_obj = umss_create_port_device(dev_mgr, pdriver)) == NULL)
{
usb_free_mem(pdriver->driver_ext);
pdriver->driver_ext = NULL;
pdriver->driver_ext_size = 0;
pdriver->disp_tbl.dev_connect = NULL;
pdriver->disp_tbl.dev_stop = NULL;
pdriver->disp_tbl.dev_disconnect = NULL;
return FALSE;
}
//
// let's load the class driver
//
umss_load_class_driver(NULL);
// umss_schedule_workitem( NULL, umss_load_class_driver, NULL, 0 );
usb_dbg_print(DBGLVL_MAXIMUM, ("umss_if_driver_init(): umss driver is initialized\n"));
return TRUE;
}
// get the driver reg information for pnp notification to class
// driver.
// bug??? how if the driver info is returned while the driver
// is being unloaded.
// So the routine must be called when usb_query_and_lock_dev is
// called.
PCLASS_DRV_REG_INFO
umss_get_if_driver_info(PUSB_DEV_MANAGER dev_mgr, PUSB_DEV pdev, DEV_HANDLE if_handle)
{
PUMSS_DRVR_EXTENSION drvr_ext;
ULONG if_idx;
USE_BASIC_NON_PENDING_IRQL;
UNREFERENCED_PARAMETER(dev_mgr);
if_idx = if_idx_from_handle(if_handle);
if (if_idx >= 4) // max interfaces per config supports. defined in td.h
return NULL;
ASSERT(pdev != NULL);
lock_dev(pdev, FALSE);
if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
{
unlock_dev(pdev, FALSE);
usb_unlock_dev(pdev);
return NULL;
}
drvr_ext = NULL;
if (pdev->usb_config->interf[if_idx].pif_drv)
drvr_ext = (PUMSS_DRVR_EXTENSION) pdev->usb_config->interf[if_idx].pif_drv->driver_ext;
else
TRAP();
unlock_dev(pdev, FALSE);
if (drvr_ext == NULL)
{
return NULL;
}
return &drvr_ext->class_driver_info;
}
VOID NTAPI
umss_worker(IN PVOID reference)
{
PUMSS_WORKER_PACKET worker_packet;
PUSB_DEV pdev;
usb_dbg_print(DBGLVL_MAXIMUM, ("umss_worker(): entering...\n"));
worker_packet = (PUMSS_WORKER_PACKET) reference;
worker_packet->completion(worker_packet->context);
if (worker_packet->dev_mgr && worker_packet->pdev)
{
pdev = (PUSB_DEV) worker_packet->pdev;
usb_unlock_dev(pdev);
pdev = NULL;
}
usb_free_mem(worker_packet);
usb_dbg_print(DBGLVL_MAXIMUM, ("umss_worker(): exit\n"));
}
/*++
Routine Description:
Wrapper for handling worker thread callbacks, it is importent to
lock the dev from being deleted by calling usb_query_and_lock_dev
and in umss_worker, call the usb_unlock_dev to release the ref
count. One exception is that the umss_if_disconnect call this
function to delete the device object that is still held by some
others, and deferred deletion is required.
Arguments:
Routine - Routine to be called when this work-item is processed
Context - Value to be passed to worker routine
Return Value:
TRUE if work item queued
FALSE if work item not queued
--*/
BOOLEAN
umss_schedule_workitem(
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?