📄 usb.c
字号:
for(i = 0; i < if_count; i++)
{
ret = usb_skip_if_and_altif((PUCHAR *) & pif_desc2);
if (ret == FALSE)
break;
}
if (ret)
*pconfig_desc_BUF = (PUCHAR) pif_desc2;
}
}
return ret;
}
PUSB_CONFIGURATION_DESC
usb_find_config_desc_by_idx(PUCHAR pbuf, LONG idx, LONG cfg_count)
{
LONG i;
BOOLEAN ret;
PUSB_CONFIGURATION_DESC pcfg_desc = (PUSB_CONFIGURATION_DESC) pbuf;
if (pcfg_desc == NULL)
return NULL;
if (cfg_count > MAX_CONFIGS_PER_DEV)
return NULL;
if (idx > cfg_count)
return NULL;
if (idx == 0)
return pcfg_desc;
for(i = 0; i < idx - 1; i++)
{
ret = usb_skip_one_config((PBYTE *) & pcfg_desc);
if (ret == FALSE)
return NULL;
}
return pcfg_desc;
}
PUSB_CONFIGURATION_DESC
usb_find_config_desc_by_val(PBYTE pbuf, LONG val, LONG cfg_count)
{
LONG i;
BOOLEAN ret;
PUSB_CONFIGURATION_DESC pcfg_desc = (PUSB_CONFIGURATION_DESC) pbuf;
if (pcfg_desc == NULL)
return NULL;
if (cfg_count > MAX_CONFIGS_PER_DEV)
return NULL;
for(i = 0; i < cfg_count; i++)
{
if (pcfg_desc->bConfigurationValue == val)
return pcfg_desc;
ret = usb_skip_one_config((PBYTE *) & pcfg_desc);
if (ret == FALSE)
return NULL;
}
return NULL;
}
#define if_from_handle( handle ) ( ( handle & 0xff00 ) >> 8 )
NTSTATUS
usb_submit_config_urb(PURB purb)
{
PUSB_DEV pdev;
PUSB_DEV_MANAGER dev_mgr;
PUSB_ENDPOINT pendp;
PURB purb1;
PUSB_CTRL_SETUP_PACKET psetup;
NTSTATUS status;
PHCD hcd;
USE_BASIC_NON_PENDING_IRQL;
if (purb == NULL)
return STATUS_INVALID_PARAMETER;
pdev = purb->pdev;
pendp = purb->pendp;
lock_dev(pdev, FALSE);
dev_mgr = dev_mgr_from_dev(pdev);
hcd = pdev->hcd;
if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
{
status = STATUS_DEVICE_DOES_NOT_EXIST;
goto LBL_OUT;
}
if (dev_state(pdev) == USB_DEV_STATE_FIRST_CONFIG || dev_state(pdev) == USB_DEV_STATE_RECONFIG)
{
//outstanding request of set configuration exists in process
status = STATUS_UNSUCCESSFUL;
goto LBL_OUT;
}
psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
if (dev_state(pdev) == USB_DEV_STATE_CONFIGURED
&& pdev->usb_config->pusb_config_desc->bConfigurationValue == (BYTE) psetup->wValue)
{
//already the current config
status = STATUS_SUCCESS;
goto LBL_OUT;
}
if (dev_state(pdev) == USB_DEV_STATE_CONFIGURED)
{
// not support re-configuration yet
status = STATUS_NOT_SUPPORTED;
goto LBL_OUT;
}
psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
purb1 = usb_alloc_mem(NonPagedPool, sizeof(URB));
if (purb1 == NULL)
{
status = STATUS_NO_MEMORY;
goto LBL_OUT;
}
UsbBuildSelectConfigurationRequest(purb1,
usb_make_handle(pdev->dev_id, 0, 0) | 0xffff,
psetup->wValue, usb_config_dev_completion, 0, ((ULONG) purb));
purb1->pdev = pdev;
purb1->pendp = pendp;
//change the dev state
pdev->flags &= ~USB_DEV_STATE_MASK;
pdev->flags |= USB_DEV_STATE_FIRST_CONFIG;
unlock_dev(pdev, FALSE);
status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb1);
if (status != STATUS_PENDING)
{
usb_free_mem(purb1);
purb1 = NULL;
}
return status;
LBL_OUT:
unlock_dev(pdev, FALSE);
return status;
}
NTSTATUS
usb_submit_urb(PUSB_DEV_MANAGER dev_mgr, PURB purb)
{
NTSTATUS status;
PUSB_DEV pdev;
LONG if_idx, endp_idx;
DEV_HANDLE endp_handle;
PUSB_CTRL_SETUP_PACKET psetup;
PUSB_ENDPOINT pendp;
PHCD hcd;
USE_BASIC_NON_PENDING_IRQL;
if (purb == NULL || dev_mgr == NULL)
return STATUS_INVALID_PARAMETER;
endp_handle = purb->endp_handle;
if (endp_handle == 0)
return STATUS_INVALID_PARAMETER;
status = usb_query_and_lock_dev(dev_mgr, endp_handle, &pdev);
if (status != STATUS_SUCCESS)
{
return status;
}
if_idx = if_idx_from_handle(endp_handle);
endp_idx = endp_idx_from_handle(endp_handle);
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;
}
if (dev_state(pdev) < USB_DEV_STATE_ADDRESSED)
{
unlock_dev(pdev, FALSE);
status = STATUS_DEVICE_NOT_READY;
goto LBL_OUT;
}
dev_mgr = dev_mgr_from_dev(pdev);
hcd = pdev->hcd;
if (default_endp_handle(endp_handle))
{
//default endp
pendp = &pdev->default_endp;
}
else if (if_idx >= MAX_INTERFACES_PER_CONFIG || endp_idx >= MAX_ENDPS_PER_IF)
{
status = STATUS_INVALID_PARAMETER;
unlock_dev(pdev, FALSE);
goto LBL_OUT;
}
else
{
if (dev_state(pdev) < USB_DEV_STATE_CONFIGURED)
{
status = STATUS_DEVICE_NOT_READY;
unlock_dev(pdev, FALSE);
goto LBL_OUT;
}
pendp = &pdev->usb_config->interf[if_idx].endp[endp_idx];
}
purb->pdev = pdev;
purb->pendp = pendp;
//for default endpoint we have some special process
if (default_endp_handle(endp_handle))
{
psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
if (psetup->bmRequestType == 0 && psetup->bRequest == USB_REQ_SET_CONFIGURATION)
{
unlock_dev(pdev, FALSE);
status = usb_submit_config_urb(purb);
goto LBL_OUT;
}
else if (psetup->bmRequestType == 1 && psetup->bRequest == USB_REQ_SET_INTERFACE)
{
unlock_dev(pdev, FALSE);
// status = STATUS_NOT_SUPPORTED;
status = usb_set_interface(purb);
goto LBL_OUT;
}
else if (psetup->bmRequestType == 0x80 && psetup->bRequest == USB_REQ_GET_DESCRIPTOR)
{
if ((psetup->wValue >> 8) == USB_DT_CONFIG || (psetup->wValue >> 8) == USB_DT_DEVICE)
{
unlock_dev(pdev, FALSE);
status = usb_get_descriptor(pdev, purb);
goto LBL_OUT;
//get the descriptor directly
//status = hcd->hcd_submit_urb( hcd, pdev, purb->pendp, purb );
//goto LBL_OUT;
}
}
else if (psetup->bmRequestType == 0x02 && psetup->bRequest == USB_REQ_CLEAR_FEATURE && psetup->wValue == 0) //reset pipe
{
ULONG endp_addr;
BOOLEAN found;
endp_addr = psetup->wIndex;
if ((endp_addr & 0xf) == 0)
{
unlock_dev(pdev, FALSE);
status = STATUS_INVALID_PARAMETER;
goto LBL_OUT;
}
// search for the endp by the endp addr in the wIndex
found = FALSE;
for(if_idx = 0; if_idx < pdev->usb_config->if_count; if_idx++)
{
for(endp_idx = 0; endp_idx < pdev->usb_config->interf[if_idx].endp_count; endp_idx++)
{
pendp = &pdev->usb_config->interf[if_idx].endp[endp_idx];
if (pendp->pusb_endp_desc->bEndpointAddress == endp_addr)
{
found = TRUE;
break;
}
}
if (found == TRUE)
break;
}
if (found)
endp_handle = usb_make_handle(pdev->dev_id, if_idx, endp_idx);
else
{
unlock_dev(pdev, FALSE);
status = STATUS_INVALID_PARAMETER;
goto LBL_OUT;
}
unlock_dev(pdev, FALSE);
status = usb_reset_pipe_ex(dev_mgr, endp_handle, usb_reset_pipe_from_dispatch_completion, purb);
goto LBL_OUT;
}
}
unlock_dev(pdev, FALSE);
status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb);
LBL_OUT:
usb_unlock_dev(pdev);
return status;
}
void
usb_config_dev_completion(PURB purb, PVOID context)
{
PURB puser_urb;
PUSB_DEV pdev;
PUSB_ENDPOINT pendp;
PUSB_CTRL_SETUP_PACKET psetup;
ULONG config_val;
NTSTATUS status;
USE_BASIC_NON_PENDING_IRQL;
UNREFERENCED_PARAMETER(context);
if (purb == NULL)
{
return;
}
pdev = purb->pdev;
pendp = purb->pendp;
if (pdev == NULL)
return;
if (purb->reference != 0)
puser_urb = (PURB) purb->reference;
else
puser_urb = NULL;
lock_dev(pdev, TRUE);
if (puser_urb)
puser_urb->status = purb->status;
if (purb->status != STATUS_SUCCESS)
{
if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
{
goto LBL_OUT;
}
if (dev_state(pdev) == USB_DEV_STATE_FIRST_CONFIG)
{
pdev->flags &= ~USB_DEV_STATE_MASK;
pdev->flags |= USB_DEV_STATE_ADDRESSED;
}
else if (dev_state(pdev) == USB_DEV_STATE_RECONFIG)
{
pdev->flags &= ~USB_DEV_STATE_MASK;
pdev->flags |= USB_DEV_STATE_CONFIGURED;
}
goto LBL_OUT;
}
// now let's construct usb_config
if (!pdev->usb_config)
{
psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
config_val = psetup->wValue;
status = dev_mgr_build_usb_config(pdev,
&pdev->desc_buf[sizeof(USB_DEVICE_DESC)],
config_val, pdev->pusb_dev_desc->bNumConfigurations);
if (status != STATUS_SUCCESS)
{
pdev->flags &= ~USB_DEV_STATE_MASK;
pdev->flags |= USB_DEV_STATE_ADDRESSED;
goto LBL_OUT;
}
pdev->flags &= ~USB_DEV_STATE_MASK;
pdev->flags |= USB_DEV_STATE_CONFIGURED;
//this usb dev represents physical dev
if (pdev->pusb_dev_desc->bDeviceClass == USB_CLASS_HUB && pdev->pusb_dev_desc->bDeviceSubClass == 0)
{
pdev->flags &= ~USB_DEV_CLASS_MASK;
pdev->flags |= USB_DEV_CLASS_HUB;
}
else if (pdev->pusb_dev_desc->bDeviceClass == USB_CLASS_MASS_STORAGE
&& pdev->pusb_dev_desc->bDeviceSubClass == 0)
{
pdev->flags &= ~USB_DEV_CLASS_MASK;
pdev->flags |= USB_DEV_CLASS_MASSSTOR;
}
else
{
pdev->flags &= ~USB_DEV_CLASS_MASK;
pdev->flags |= USB_DEV_CLASS_SCANNER;
}
}
else
{
//not supported
puser_urb->status = STATUS_NOT_SUPPORTED;
pdev->flags &= ~USB_DEV_STATE_MASK;
pdev->flags |= USB_DEV_STATE_CONFIGURED;
}
LBL_OUT:
unlock_dev(pdev, TRUE);
usb_free_mem(purb);
if (puser_urb && puser_urb->completion)
puser_urb->completion(puser_urb, puser_urb->context);
return;
}
NTSTATUS
usb_get_descriptor(PUSB_DEV pdev, PURB purb)
{
PUSB_CTRL_SETUP_PACKET psetup;
LONG idx, size, count, i;
PBYTE buf;
PUSB_CONFIGURATION_DESC pcfg_desc1;
USE_BASIC_NON_PENDING_IRQL;
if (pdev == NULL || purb == NULL)
return STATUS_INVALID_PARAMETER;
if (purb->data_buffer == NULL || purb->data_length == 0)
{
return purb->status = STATUS_INVALID_PARAMETER;
}
lock_dev(pdev, FALSE);
psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
if (pdev->desc_buf == NULL)
{
purb->status = STATUS_DEVICE_NOT_READY;
goto LBL_OUT;
}
if ((psetup->wValue >> 8) == USB_DT_CONFIG)
{
idx = (psetup->wValue & 0xff);
count = pdev->pusb_dev_desc->bNumConfigurations;
if (idx >= count)
{
purb->status = STATUS_INVALID_PARAMETER;
goto LBL_OUT;
}
buf = &pdev->desc_buf[sizeof(USB_DEVICE_DESC)];
pcfg_desc1 = usb_find_config_desc_by_idx(buf, idx, count);
if (pcfg_desc1 == NULL)
{
purb->status = STATUS_UNSUCCESSFUL;
goto LBL_OUT;
}
size = pcfg_desc1->wTotalLength;
size = size > purb->data_length ? purb->data_length : size;
for(i = 0; i < size; i++)
{
purb->data_buffer[i] = ((PBYTE) pcfg_desc1)[i];
}
purb->status = STATUS_SUCCESS;
goto LBL_OUT;
}
else if ((psetup->wValue >> 8) == USB_DT_DEVICE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -