⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
            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 + -