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 + -
显示快捷键?