📄 hub.c
字号:
hub_start_next_reset_port(dev_mgr, TRUE);
return FALSE;
}
VOID
hub_reexamine_port_status_queue(PUSB_DEV hub_dev, ULONG port_idx, BOOLEAN from_dpc)
{
PHUB2_EXTENSION hub_ext;
PUSB_DEV_MANAGER dev_mgr;
USE_NON_PENDING_IRQL;;
if (hub_dev == NULL || port_idx == 0)
return;
dev_mgr = dev_mgr_from_dev(hub_dev);
if (from_dpc)
KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock);
else
KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql);
lock_dev(hub_dev, TRUE);
if (dev_state(hub_dev) != USB_DEV_STATE_ZOMB)
{
hub_ext = hub_ext_from_dev(hub_dev);
if (psq_is_empty(&hub_ext->port_status_queue[port_idx]))
{
set_port_state(hub_ext->port_status_queue[port_idx].port_flags, STATE_IDLE);
}
else
{
set_port_state(hub_ext->port_status_queue[port_idx].port_flags, STATE_EXAMINE_STATUS_QUE);
hub_post_esq_event(hub_dev, (UCHAR) port_idx, hub_event_examine_status_que);
}
}
unlock_dev(hub_dev, TRUE);
if (from_dpc)
KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
else
KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
return;
}
BOOLEAN
hub_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle)
{
URB urb, *purb;
CHAR buf[512];
DEV_HANDLE endp_handle;
USB_DEVICE_DESC dev_desc;
PUSB_CONFIGURATION_DESC pcfg_desc;
PUSB_INTERFACE_DESC pif_desc;
PUSB_CTRL_SETUP_PACKET psetup;
NTSTATUS status;
LONG i, j, found, cfg_val = 0;
PUSB_DEV_MANAGER dev_mgr;
PUSB_DEV pdev;
if (param == NULL || dev_handle == 0)
return FALSE;
dev_mgr = param->dev_mgr;
pcfg_desc = (PUSB_CONFIGURATION_DESC) buf;
endp_handle = dev_handle | 0xffff;
UsbBuildGetDescriptorRequest(&urb,
endp_handle,
USB_DT_DEVICE, 0, 0, (&dev_desc), (sizeof(USB_DEVICE_DESC)), NULL, 0, 0);
status = usb_submit_urb(dev_mgr, &urb);
if (status != STATUS_SUCCESS)
return FALSE;
found = FALSE;
for(i = 0; i < dev_desc.bNumConfigurations; i++)
{
UsbBuildGetDescriptorRequest(&urb, endp_handle, USB_DT_CONFIG, (USHORT) i, 0, buf, 512, NULL, 0, 0);
status = usb_submit_urb(dev_mgr, &urb);
if (status != STATUS_SUCCESS)
{
return FALSE;
}
status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
if (status != STATUS_SUCCESS)
return FALSE;
pif_desc = (PUSB_INTERFACE_DESC) & buf[sizeof(USB_CONFIGURATION_DESC)];
for(j = 0; j < pcfg_desc->bNumInterfaces; j++)
{
if (pif_desc->bInterfaceClass == USB_CLASS_HUB
&& pif_desc->bInterfaceSubClass == 0 && pif_desc->bNumEndpoints == 1)
{
if ((pif_desc->bInterfaceProtocol > 0 && pif_desc->bInterfaceProtocol < 3)
|| (pif_desc->bInterfaceProtocol == 0 && pdev->flags & USB_DEV_FLAG_HIGH_SPEED)
|| (pif_desc->bInterfaceProtocol == 0 && !usb2(pdev->hcd)))
{
found = TRUE;
cfg_val = pcfg_desc->bConfigurationValue;
break;
}
}
if (usb_skip_if_and_altif((PBYTE *) & pif_desc) == FALSE)
{
break;
}
}
usb_unlock_dev(pdev);
if (found)
break;
if (usb_skip_one_config((PBYTE *) & pcfg_desc) == FALSE)
{
break;
}
}
if (found)
{
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 = endp_handle;
purb->data_buffer = NULL;
purb->data_length = 0;
purb->completion = hub_set_cfg_completion;
purb->context = dev_mgr;
purb->reference = (LONG) param->pdriver;
psetup->bmRequestType = 0;
psetup->bRequest = USB_REQ_SET_CONFIGURATION;
psetup->wValue = (USHORT) cfg_val;
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;
}
return FALSE;
}
VOID hub_set_interface_completion(PURB purb, PVOID pcontext);
VOID
hub_set_cfg_completion(PURB purb, PVOID pcontext)
{
PUSB_DEV_MANAGER dev_mgr;
PUSB_DRIVER pdriver;
ULONG endp_handle, dev_handle;
PUSB_CTRL_SETUP_PACKET psetup;
UCHAR if_idx = 0;
PUSB_DEV pdev;
PUSB_INTERFACE pif;
BOOLEAN high_speed, multiple_tt;
NTSTATUS status;
USE_BASIC_NON_PENDING_IRQL;;
if (purb == NULL || pcontext == NULL)
return;
//pdev = NULL;
dev_mgr = (PUSB_DEV_MANAGER) pcontext;
endp_handle = purb->endp_handle;
dev_handle = endp_handle & 0xffff0000;
pdriver = (PUSB_DRIVER) purb->reference;
high_speed = FALSE;
multiple_tt = FALSE;
if (purb->status != STATUS_SUCCESS)
{
goto LBL_ERROR;
}
status = usb_query_and_lock_dev(dev_mgr, purb->endp_handle, &pdev);
if (status != STATUS_SUCCESS)
{
usb_unlock_dev(pdev);
goto LBL_ERROR;
}
lock_dev(pdev, TRUE);
if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
{
unlock_dev(pdev, TRUE);
usb_unlock_dev(pdev);
goto LBL_ERROR;
}
if (pdev->flags & USB_DEV_FLAG_HIGH_SPEED)
{
high_speed = TRUE;
hub_if_from_dev(pdev, pif);
if (pif->altif_count)
{
multiple_tt = TRUE;
if_idx = pif - &pdev->usb_config->interf[0];
}
}
unlock_dev(pdev, TRUE);
usb_unlock_dev(pdev);
if (!high_speed || !multiple_tt)
{
hub_set_interface_completion(purb, pcontext);
return;
}
psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
urb_init((purb));
// set the mult-tt if exist
purb->endp_handle = endp_handle;
purb->data_buffer = NULL;
purb->data_length = 0;
purb->completion = hub_set_interface_completion;
purb->context = dev_mgr;
purb->reference = (LONG) pdriver;
psetup->bmRequestType = 0;
psetup->bRequest = USB_REQ_SET_INTERFACE;
psetup->wValue = (USHORT) 1; // alternate tt
psetup->wIndex = if_idx; // if index
psetup->wLength = 0;
status = usb_submit_urb(dev_mgr, purb);
if (status == STATUS_PENDING)
return;
LBL_ERROR:
usb_free_mem(purb);
purb = NULL;
return;
}
void
hub_set_interface_completion(PURB purb, PVOID pcontext)
{
NTSTATUS status;
PUSB_CTRL_SETUP_PACKET psetup;
PUSB_DEV_MANAGER dev_mgr;
PBYTE dev_ext;
DEV_HANDLE endp_handle;
PUSB_DRIVER pdriver;
if (purb == NULL || pcontext == NULL)
return;
//pdev = NULL;
dev_mgr = (PUSB_DEV_MANAGER) pcontext;
endp_handle = purb->endp_handle;
pdriver = (PUSB_DRIVER) purb->reference;
if (purb->status != STATUS_SUCCESS)
{
usb_free_mem(purb);
return;
}
dev_ext = usb_alloc_mem(NonPagedPool, sizeof(HUB2_EXTENSION));
if (dev_ext == NULL)
{
goto LBL_OUT;
}
//
//acquire hub descriptor
//
RtlZeroMemory(dev_ext, sizeof(HUB2_EXTENSION));
urb_init(purb);
purb->data_buffer = (PUCHAR) & ((HUB2_EXTENSION *) dev_ext)->hub_desc;
purb->endp_handle = endp_handle;
purb->data_length = sizeof(USB_HUB_DESCRIPTOR);
purb->completion = hub_get_hub_desc_completion;
purb->context = (PVOID) dev_mgr;
purb->reference = (ULONG) dev_ext;
purb->pirp = (PIRP) pdriver;
psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
psetup->bmRequestType = 0xa0;
psetup->bRequest = USB_REQ_GET_DESCRIPTOR;
psetup->wValue = (0x29 << 8);
psetup->wLength = sizeof(USB_HUB_DESCRIPTOR);
status = usb_submit_urb(dev_mgr, purb);
if (status != STATUS_PENDING)
{
usb_free_mem(dev_ext);
goto LBL_OUT;
}
return;
LBL_OUT:
//clear the dev_driver fields in the dev.
usb_free_mem(purb);
return;
}
VOID
hub_power_on_port_completion(PURB purb, PVOID pcontext)
{
PUSB_DEV_MANAGER dev_mgr;
if (purb == NULL)
return;
if (pcontext == NULL)
goto LBL_OUT;
dev_mgr = (PUSB_DEV_MANAGER) pcontext;
if (purb->status != STATUS_SUCCESS)
{
usb_dbg_print(DBGLVL_MAXIMUM,
("hub_power_on_port_completion(): port%d power on failed\n", purb->reference));
}
else
{
usb_dbg_print(DBGLVL_MAXIMUM,
("hub_power_on_port_completion(): port%d power on succeed\n", purb->reference));
}
LBL_OUT:
usb_free_mem(purb);
return;
}
NTSTATUS
hub_power_on_port(PUSB_DEV pdev, UCHAR port_idx)
{
NTSTATUS status;
PUSB_CTRL_SETUP_PACKET psetup;
PUSB_DEV_MANAGER dev_mgr;
PURB purb;
PHCD hcd;
USE_BASIC_NON_PENDING_IRQL;;
if (pdev == NULL || port_idx == 0)
return STATUS_INVALID_PARAMETER;
purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
if (purb == NULL)
return STATUS_NO_MEMORY;
urb_init(purb);
lock_dev(pdev, FALSE);
if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
{
unlock_dev(pdev, FALSE);
status = STATUS_DEVICE_DOES_NOT_EXIST;
goto LBL_OUT;
}
dev_mgr = dev_mgr_from_dev(pdev);
hcd = pdev->hcd;
purb->completion = hub_power_on_port_completion;
purb->context = (PVOID) dev_mgr;
purb->reference = (ULONG) port_idx;
purb->pdev = pdev;
purb->pendp = &pdev->default_endp;
psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
psetup->bmRequestType = 0x23;
psetup->bRequest = USB_REQ_SET_FEATURE;
psetup->wValue = USB_PORT_FEAT_POWER;
psetup->wIndex = (WORD) port_idx;
psetup->wLength = 0;
unlock_dev(pdev, FALSE);
status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb);
if (status != STATUS_PENDING)
{
goto LBL_OUT;
}
return STATUS_PENDING;
LBL_OUT:
usb_free_mem(purb);
return status;
}
void
hub_get_hub_desc_completion(PURB purb, PVOID pcontext)
{
PUSB_DEV_MANAGER dev_mgr;
PHUB2_EXTENSION hub_ext;
PUSB_DEV pdev;
LONG i;
PUSB_INTERFACE pif = NULL;
ULONG status;
LONG port_count;
PUSB_DRIVER pdriver;
DEV_HANDLE dev_handle;
USE_BASIC_NON_PENDING_IRQL;;
if (purb == NULL)
{
return;
}
dev_mgr = (PUSB_DEV_MANAGER) pcontext;
hub_ext = (PHUB2_EXTENSION) purb->reference;
pdriver = (PUSB_DRIVER) purb->pirp;
dev_handle = purb->endp_handle & 0xffff0000;
if (pcontext == NULL || purb->reference == 0)
goto LBL_OUT;
if (purb->status != STATUS_SUCCESS)
{
goto LBL_OUT;
}
// obtain the pointer to the dev
status = usb_query_and_lock_dev(dev_mgr, purb->endp_handle, &pdev);
if (status != STATUS_SUCCESS)
{
usb_unlock_dev(pdev);
goto LBL_OUT;
}
// safe to release the pdev ref since we are in urb completion
usb_unlock_dev(pdev);
lock_dev(pdev, TRUE);
if (dev_state(pdev) == USB_DEV_STATE_ZOMB ||
dev_mgr_set_driver(dev_mgr, dev_handle, pdriver, pdev) == FALSE)
{
unlock_dev(pdev, TRUE);
goto LBL_OUT;
}
//transit the state to configured
pdev->flags &= ~USB_DEV_STATE_MASK;
pdev->flags |= USB_DEV_STATE_CONFIGURED;
pdev->dev_ext = (PBYTE) hub_ext;
pdev->dev_ext_size = sizeof(HUB2_EXTENSION);
port_count = hub_ext->port_count = hub_ext->hub_desc.bNbrPorts;
hub_ext->pdev = pdev;
for(i = 0; i < pdev->usb_config->if_count; i++)
{
pif = &pdev->usb_config->interf[i];
if (pif->pusb_if_desc->bInterfaceClass ==
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -