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

📄 devmgr.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
            usb_free_mem(pdev->desc_buf);
            pdev->desc_buf_size = 0;
            pdev->desc_buf = NULL;
            pdev->pusb_dev_desc = NULL;
            pdev->usb_config = NULL;
        }
    }
    unlock_dev(pdev, TRUE);

    return;
}

BOOLEAN
dev_mgr_start_select_driver(PUSB_DEV pdev)
{
    PUSB_DEV_MANAGER dev_mgr;
    PUSB_EVENT pevent;
    BOOLEAN bret;

    USE_BASIC_NON_PENDING_IRQL;;

    if (pdev == NULL)
        return FALSE;

    dev_mgr = dev_mgr_from_dev(pdev);
    KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock);
    lock_dev(pdev, TRUE);

    if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
    {
        bret = FALSE;
        goto LBL_OUT;
    }

    pevent = alloc_event(&dev_mgr->event_pool, 1);
    if (pevent == NULL)
    {
        bret = FALSE;
        goto LBL_OUT;
    }
    pevent->flags = USB_EVENT_FLAG_ACTIVE;
    pevent->event = USB_EVENT_DEFAULT;
    pevent->pdev = pdev;
    pevent->context = 0;
    pevent->param = 0;
    pevent->pnext = 0;          //vertical queue for serialized operation
    pevent->process_event = dev_mgr_event_select_driver;
    pevent->process_queue = event_list_default_process_queue;

    InsertTailList(&dev_mgr->event_list, &pevent->event_link);
    KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE);
    bret = TRUE;

LBL_OUT:
    unlock_dev(pdev, TRUE);
    KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
    return bret;
}

BOOLEAN
dev_mgr_connect_to_dev(PVOID Parameter)
{
    PUSB_DEV pdev;
    DEV_HANDLE dev_handle;
    NTSTATUS status;
    PUSB_DRIVER pdriver;
    PDEV_CONNECT_DATA pcd = (PDEV_CONNECT_DATA) Parameter;
    PUSB_DEV_MANAGER dev_mgr;
    DEV_CONNECT_DATA param;

    if (pcd == NULL)
        return FALSE;
    dev_handle = pcd->dev_handle;
    pdriver = pcd->pdriver;
    dev_mgr = pcd->dev_mgr;

    param.dev_mgr = dev_mgr;
    param.pdriver = pdriver;
    param.dev_handle = 0;       //not used

    status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
    if (status != STATUS_SUCCESS)
        return FALSE;

    usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_connect_to_dev(): about to call driver's dev_connect\n"));
    status = pdriver->disp_tbl.dev_connect(&param, dev_handle);
    usb_unlock_dev(pdev);
    return status;
}

VOID
dev_mgr_event_select_driver(PUSB_DEV pdev, ULONG event, ULONG context, ULONG param)
{
    PUSB_DEV_MANAGER dev_mgr;
    PUSB_DRIVER pdriver, pcand;
    LONG credit, match, i;
    DEV_HANDLE handle = 0;
    DEV_CONNECT_DATA cd;

    USE_BASIC_NON_PENDING_IRQL;

    UNREFERENCED_PARAMETER(param);
    UNREFERENCED_PARAMETER(context);

    usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_event_select_driver(): pdev=%p event=0x%x\n", pdev, event));

    if (pdev == NULL)
        return;

    lock_dev(pdev, FALSE);
    if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
    {
        unlock_dev(pdev, FALSE);
        return;
    }
    dev_mgr = dev_mgr_from_dev(pdev);

    pcand = NULL;
    match = 0;
    for(i = HUB_DRIVER_IDX; i < DEVMGR_MAX_DRIVERS; i++)
    {
        //bypass root-hub driver with idx zero
        pdriver = (PUSB_DRIVER) & dev_mgr->driver_list[i];

        if (pdriver->driver_desc.flags & USB_DRIVER_FLAG_DEV_CAPABLE)
            credit = dev_mgr_score_driver_for_dev(dev_mgr, pdriver, pdev->pusb_dev_desc);
        else
        {
            continue;
        }
        if (credit > match)
            pcand = pdriver, match = credit;

    }

    if (match)
    {
        // we set class driver here
        // pdev->dev_driver = pcand;
        handle = usb_make_handle(pdev->dev_id, 0, 0);
    }
    unlock_dev(pdev, FALSE);

    if (match)
    {

        cd.dev_handle = handle;
        cd.pdriver = pcand;
        cd.dev_mgr = dev_mgr;

        if (dev_mgr_connect_to_dev(&cd))
            return;

        // ExInitializeWorkItem( pwork_item, dev_mgr_connect_to_dev, ( PVOID )pcd );
        // ExQueueWorkItem( pwork_item, DelayedWorkQueue );
    }
    cd.dev_handle = handle;
    cd.pdriver = &dev_mgr->driver_list[GEN_DRIVER_IDX];
    cd.dev_mgr = dev_mgr;
    dev_mgr_connect_to_dev(&cd);
    return;
}

BOOLEAN
dev_mgr_build_usb_endp(PUSB_INTERFACE pif, PUSB_ENDPOINT pendp, PUSB_ENDPOINT_DESC pendp_desc)
{
    if (pendp == NULL || pif == NULL || pendp_desc == NULL)
        return FALSE;

    pendp->flags = 0;
    InitializeListHead(&pendp->urb_list);       //pending urb queue
    pendp->pusb_if = pif;
    pendp->pusb_endp_desc = pendp_desc;
    return TRUE;
}

BOOLEAN
dev_mgr_build_usb_if(PUSB_CONFIGURATION pcfg, PUSB_INTERFACE pif, PUSB_INTERFACE_DESC pif_desc, BOOLEAN alt_if)
{
    LONG i;
    PUSB_ENDPOINT_DESC pendp_desc;

    if (pcfg == NULL || pif == NULL || pif_desc == NULL)
        return FALSE;

    if (alt_if == FALSE)
    {
        pif->endp_count = pif_desc->bNumEndpoints > MAX_ENDPS_PER_IF
            ? MAX_ENDPS_PER_IF : pif_desc->bNumEndpoints;

        pif->pif_drv = NULL;
        pif->pusb_config = pcfg;
        pif->pusb_if_desc = pif_desc;
        pif->if_ext_size = 0;
        pif->if_ext = NULL;

        InitializeListHead(&pif->altif_list);
        pif->altif_count = 0;

        pendp_desc = (PUSB_ENDPOINT_DESC) (&((PBYTE) pif_desc)[sizeof(USB_INTERFACE_DESC)]);

        for(i = 0; i < pif->endp_count; i++, pendp_desc++)
        {
            dev_mgr_build_usb_endp(pif, &pif->endp[i], pendp_desc);
        }
    }
    else
    {
        PUSB_INTERFACE paltif;
        PLIST_ENTRY pthis, pnext;

        pif->altif_count++;
        paltif = usb_alloc_mem(NonPagedPool, sizeof(USB_INTERFACE));
        RtlZeroMemory(paltif, sizeof(USB_INTERFACE));
        InsertTailList(&pif->altif_list, &paltif->altif_list);
        paltif->pif_drv = NULL;
        paltif->pusb_config = pcfg;
        paltif->pusb_if_desc = pif_desc;
        paltif->if_ext_size = 0;
        paltif->if_ext = NULL;
        paltif->endp_count = pif_desc->bNumEndpoints > MAX_ENDPS_PER_IF
            ? MAX_ENDPS_PER_IF : pif_desc->bNumEndpoints;

        ListFirst(&pif->altif_list, pthis);

        while (pthis)
        {
            //synchronize the altif_count;
            PUSB_INTERFACE pthis_if;
            pthis_if = (PUSB_INTERFACE) (((PBYTE) pthis) - offsetof(USB_INTERFACE, altif_list));
            pthis_if->altif_count = pif->altif_count;
            ListNext(&pif->altif_list, pthis, pnext);
        }

    }
    return TRUE;
}

NTSTATUS
dev_mgr_build_usb_config(PUSB_DEV pdev, PBYTE pbuf, ULONG config_val, LONG config_count)
{
    PUSB_CONFIGURATION pcfg;
    PUSB_INTERFACE_DESC pif_desc;
    PUSB_INTERFACE pif;
    int i;
    LONG if_count;

    if (pdev == NULL || pbuf == NULL)
        return STATUS_INVALID_PARAMETER;


    pdev->usb_config = usb_alloc_mem(NonPagedPool, sizeof(USB_CONFIGURATION));
    pcfg = pdev->usb_config;

    if (pdev->usb_config == NULL)
        return STATUS_NO_MEMORY;

    RtlZeroMemory(pcfg, sizeof(USB_CONFIGURATION));
    pcfg->pusb_config_desc = usb_find_config_desc_by_val(pbuf, config_val, config_count);

    if (pcfg->pusb_config_desc == NULL)
    {
        usb_free_mem(pcfg);
        pdev->usb_config = NULL;
        return STATUS_UNSUCCESSFUL;
    }
    pcfg->if_count = pcfg->pusb_config_desc->bNumInterfaces;
    pcfg->pusb_dev = pdev;
    pif_desc = (PUSB_INTERFACE_DESC) & ((PBYTE) pcfg->pusb_config_desc)[sizeof(USB_CONFIGURATION_DESC)];
    if_count = pcfg->if_count;

    for(i = 0; i < if_count; i++, pif_desc++)
    {
        if (pif_desc->bAlternateSetting == 0)
        {
            dev_mgr_build_usb_if(pcfg, &pcfg->interf[i], pif_desc, FALSE);
        }
        else
        {
            i--;
            pif = &pcfg->interf[i];
            dev_mgr_build_usb_if(pcfg, pif, pif_desc, TRUE);
        }
    }
    return STATUS_SUCCESS;
}

NTSTATUS
dev_mgr_destroy_usb_config(PUSB_CONFIGURATION pcfg)
{
    long i;
    PLIST_ENTRY pthis;
    PUSB_INTERFACE pif;

    if (pcfg == NULL)
        return FALSE;

    for(i = 0; i < pcfg->if_count; i++)
    {
        pif = &pcfg->interf[i];

        if (pif->altif_count)
        {
            ListFirst(&pif->altif_list, pthis);
            while (pthis)
            {
                PUSB_INTERFACE pthis_if;
                pthis_if = (PUSB_INTERFACE) (((PBYTE) pthis) - offsetof(USB_INTERFACE, altif_list));
                RemoveEntryList(pthis);
                usb_free_mem(pthis_if);
                if (IsListEmpty(&pif->altif_list) == TRUE)
                    break;

                ListFirst(&pif->altif_list, pthis);
            }
        }
    }
    usb_free_mem(pcfg);
    return TRUE;
}

#define is_dev_product_match( pdriVER, pdev_DESC ) \
( ( pdriVER )->driver_desc.vendor_id == ( pdev_DESC )->idVendor \
  && ( pdriVER )->driver_desc.product_id == ( pdev_DESC )->idProduct )

LONG
dev_mgr_score_driver_for_dev(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver, PUSB_DEVICE_DESC pdev_desc)
{
    LONG credit = 0;

    UNREFERENCED_PARAMETER(dev_mgr);

    //assume supports all the sub_class are supported if sub_class is zero
    if (pdriver->driver_desc.dev_class == pdev_desc->bDeviceClass)
    {
        if (pdriver->driver_desc.dev_sub_class == 0 && pdriver->driver_desc.dev_protocol == 0)
            credit = 3;
        else if (pdriver->driver_desc.dev_sub_class == pdev_desc->bDeviceSubClass)
        {
            if (pdriver->driver_desc.dev_protocol == 0)
                credit = 6;
            else if (pdriver->driver_desc.dev_protocol == pdev_desc->bDeviceProtocol)
                credit = 9;
        }
    }

    if (is_dev_product_match(pdriver, pdev_desc))
        credit += 20;

    return credit;
}

LONG
dev_mgr_score_driver_for_if(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver, PUSB_INTERFACE_DESC pif_desc)
{
    LONG credit;

    if (pdriver == NULL
        || !(pdriver->driver_desc.flags & USB_DRIVER_FLAG_IF_CAPABLE) || pif_desc == NULL || dev_mgr == NULL)
        return 0;

    if (is_header_match((PBYTE) pif_desc, USB_DT_INTERFACE) == FALSE)
    {
        return 0;
    }

    credit = 0;
    if ((pdriver->driver_desc.if_class == pif_desc->bInterfaceClass))
    {
        if (pdriver->driver_desc.if_sub_class == 0 && pdriver->driver_desc.if_protocol == 0)
            credit = 2;
        if (pdriver->driver_desc.if_sub_class == pif_desc->bInterfaceSubClass)
        {
            if (pdriver->driver_desc.if_protocol == 0)
                credit = 4;
            if (pdriver->driver_desc.if_protocol == pif_desc->bInterfaceProtocol)
                credit = 6;
        }
    }
    else
        credit = 1;

    return credit;
}

#define is_equal_driver( pd1, pd2, ret ) \
{\
    int i;\
    ret = TRUE;\
    PUSB_DRIVER pdr1, pdr2;\
    pdr1 = ( PUSB_DRIVER )( pd1 );\
    pdr2 = ( PUSB_DRIVER ) ( pd2 );\
    for( i = 0; i < 16; i++ )\
    {\
        if( pdr1->driver_name[ i ] != pdr2->driver_name[ i ] )\
        {\
            ret = FALSE;\
            break;\
        }\
    }\
}

//return value is the hcd id
UCHAR
dev_mgr_register_hcd(PUSB_DEV_MANAGER dev_mgr, PHCD hcd)
{
    if (dev_mgr == NULL || hcd == NULL)
        return 0xff;

    if (dev_mgr->hcd_count >= MAX_HCDS)
        return 0xff;

    dev_mgr->hcd_array[dev_mgr->hcd_count++] = hcd;
    return dev_mgr->hcd_count - 1;
}

BOOLEAN
dev_mgr_register_irp(PUSB_DEV_MANAGER dev_mgr, PIRP pirp, PURB purb)
{
    if (dev_mgr == NULL)
        return FALSE;

    if (add_irp_to_list(&dev_mgr->irp_list, pirp, purb))
    {
        return TRUE;
    }
    TRAP();
    return FALSE;
}

//caller must guarantee that when this func is called,
//the urb associated must exist.
PURB
dev_mgr_remove_irp(PUSB_DEV_MANAGER dev_mgr, PIRP pirp)
{
    PURB purb;
    if (dev_mgr == NULL)
        return NULL;

    purb = remove_irp_from_list(&dev_mgr->irp_list, pirp, NULL);
    return purb;
}

VOID
dev_mgr_cancel_irp(PDEVICE_OBJECT dev_obj, PIRP pirp)
{
    PUSB_DEV_MANAGER dev_mgr;
    PDEVEXT_HEADER pdev_ext_hdr;

    pdev_ext_hdr = (PDEVEXT_HEADER) dev_obj->DeviceExtension;
    dev_mgr = pdev_ext_hdr->dev_mgr;

    if (dev_obj->CurrentIrp == pirp)
    {
        IoReleaseCancelSpinLock(pirp->CancelIrql);
        // we did not IoStartNextPacket, leave it for the urb completion
    }
    else
    {
        KeRemoveEntryDeviceQueue(&dev_obj->DeviceQueue, &pirp->Tail.Overlay.DeviceQueueEntry);
        IoReleaseCancelSpinLock(pirp->CancelIrql);

        pirp->IoStatus.Information = 0;
        pirp->IoStatus.Status = STATUS_CANCELLED;
        IoCompleteRequest(pirp, IO_NO_INCREMENT);
        // the device queue is moved on, no need to call IoStartNextPacket
        return;
    }

    //
    // remove the irp and call the dev_mgr_cancel_irp
    // the completion will be done in urb completion
    //
    remove_irp_from_list(&dev_mgr->irp_list, pirp, dev_mgr);
    return;

}

// release the hcd
VOID
dev_mgr_release_hcd(PUSB_DEV_MANAGER dev_mgr)
{
    LONG i;
    PHCD hcd;
    for(i = 0; i < dev_mgr->hcd_count; i++)
    {
        hcd = dev_mgr->hcd_array[i];
        hcd->hcd_release(hcd);
        dev_mgr->hcd_array[i] = 0;
    }
    dev_mgr->hcd_count = 0;
    return;
}

VOID
dev_mgr_start_hcd(PUSB_DEV_MANAGER dev_mgr)
{
    LONG i;
    PHCD hcd;
    for(i = 0; i < dev_mgr->hcd_count; i++)
    {
        hcd = dev_mgr->hcd_array[i];
        hcd->hcd_start(hcd);
    }
    return;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -