umss.c

来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 1,933 行 · 第 1/5 页

C
1,933
字号
/**
 * umss.c - USB driver stack project for Windows NT 4.0
 *
 * Copyright (c) 2002-2004 Zhiming  mypublic99@yahoo.com
 *
 * This program/include file is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published
 * by the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program/include file is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program (in the main directory of the distribution, the file
 * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
 * Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "usbdriver.h"

#include <srb.h>
#include <ntddscsi.h>
#include <scsi.h>

#define UMSS_EXIT_DISPATCH( dev_OBJ, staTUS, iRp ) \
{\
	iRp->IoStatus.Status = staTUS;\
    if( staTUS != STATUS_PENDING)\
    {\
		IoCompleteRequest( iRp, IO_NO_INCREMENT);\
		return staTUS;\
    }\
    IoMarkIrpPending( iRp );\
	IoStartPacket( dev_OBJ, iRp, NULL, NULL ); \
    return STATUS_PENDING;\
}

#define UMSS_COMPLETE_START_IO( dev_OBJ, staTUS, iRP ) \
{\
	iRP->IoStatus.Status = staTUS;\
	if( staTUS != STATUS_PENDING )\
	{\
		IoStartNextPacket( dev_OBJ, FALSE );\
		IoCompleteRequest( iRP, IO_NO_INCREMENT );\
	}\
	return;\
}

extern VOID gendrv_startio(IN PDEVICE_OBJECT dev_obj, IN PIRP irp);

NTSYSAPI NTSTATUS NTAPI ZwLoadDriver(IN PUNICODE_STRING DriverServiceName);

NTSYSAPI
NTSTATUS
NTAPI
ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
                   IN POBJECT_TYPE ObjectType OPTIONAL,
                   IN KPROCESSOR_MODE AccessMode,
                   IN OUT PACCESS_STATE AccessState OPTIONAL,
                   IN ACCESS_MASK DesiredAccess OPTIONAL,
                   IN OUT PVOID ParseContext OPTIONAL, OUT PHANDLE Handle);

VOID NTAPI umss_start_io(IN PDEVICE_OBJECT dev_obj, IN PIRP irp);
NTSTATUS umss_port_dispatch_routine(PDEVICE_OBJECT pdev_obj, PIRP irp);
BOOLEAN umss_connect(PDEV_CONNECT_DATA dev_mgr, DEV_HANDLE dev_handle);
BOOLEAN umss_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
BOOLEAN umss_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
NTSTATUS umss_dispatch_routine(PDEVICE_OBJECT pdev_obj, PIRP irp);
VOID umss_set_cfg_completion(PURB purb, PVOID pcontext);
VOID NTAPI umss_start_create_device(IN PVOID Parameter);
BOOLEAN umss_delete_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdrvr, PDEVICE_OBJECT dev_obj, BOOLEAN is_if);
BOOLEAN umss_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
NTSTATUS umss_process_srb(PDEVICE_OBJECT dev_obj, PIRP irp);
VOID umss_load_class_driver(PVOID context);
BOOLEAN umss_tsc_to_sff(PIO_PACKET io_packet);
VOID umss_fix_sff_result(PIO_PACKET io_packet, SCSI_REQUEST_BLOCK * srb);

PDEVICE_OBJECT
umss_create_port_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{

    // currently a port device is a connection point
    // and upper driver use this to register itself
    // with umss driver for future notification of
    // pnp event. 2004-03-22 23:12:41
    CHAR dev_name[64];
    STRING string;
    NTSTATUS status;
    PDEVICE_OBJECT pdev;
    UNICODE_STRING name_string, symb_link;
    PUMSS_PORT_DEV_EXT pdev_ext;

    sprintf(dev_name, "\\Device\\usbPort_%d", (int)0);

    RtlInitString(&string, dev_name);
    RtlAnsiStringToUnicodeString(&name_string, &string, TRUE);
    pdev = NULL;

    status = IoCreateDevice(dev_mgr->usb_driver_obj,
                            sizeof(UMSS_PORT_DEV_EXT), &name_string, FILE_USB_DEV_TYPE, 0, TRUE, &pdev);

    if (status == STATUS_SUCCESS)
    {
        //
        // We do buffered io
        //
        pdev->Flags |= DO_BUFFERED_IO;

        pdev->Flags &= ~DO_DEVICE_INITIALIZING;
        pdev->StackSize = 2;    //one for fdo, one for file device obj

        pdev_ext = (PUMSS_PORT_DEV_EXT) pdev->DeviceExtension;

        pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_CLIENT_DEV;
        pdev_ext->dev_ext_hdr.dispatch = umss_port_dispatch_routine;
        pdev_ext->dev_ext_hdr.start_io = NULL;
        pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr;
        pdev_ext->pdriver = pdriver;

        sprintf(dev_name, "\\DosDevices\\usbPort%d", (int)0);

        RtlInitString(&string, dev_name);
        RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
        IoCreateSymbolicLink(&symb_link, &name_string);
        RtlFreeUnicodeString(&symb_link);

    }

    RtlFreeUnicodeString(&name_string);
    return pdev;
}

BOOLEAN
umss_delete_port_device(PDEVICE_OBJECT dev_obj)
{
    CHAR dev_name[64];
    STRING string;
    UNICODE_STRING symb_link;

    if (dev_obj == NULL)
        return FALSE;

    // remove the symbolic link
    sprintf(dev_name, "\\DosDevices\\usbPort%d", (int)0);
    RtlInitString(&string, dev_name);
    RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
    IoDeleteSymbolicLink(&symb_link);
    RtlFreeUnicodeString(&symb_link);

    if (dev_obj->ReferenceCount == 0)
    {
        IoDeleteDevice(dev_obj);
        usb_dbg_print(DBGLVL_MAXIMUM, ("umss_delete_port_device(): port device object is removed\n"));
    }
    return TRUE;
}

// FIXME!!! there can not be sent IOCTL_SUBMIT_URB_XXX while
// the IOCTL_SUBMIT_CDB_XXX are active. may confuse the device.
// not resolved yet.
// 2004-03-22 23:12:26
NTSTATUS
umss_port_dispatch_routine(PDEVICE_OBJECT pdev_obj, PIRP irp)
{
    ULONG ctrl_code;
    NTSTATUS status;
    PIO_STACK_LOCATION irp_stack;
    PUMSS_PORT_DEV_EXT pdev_ext;
    PUMSS_DRVR_EXTENSION pdrvr_ext;

    if (pdev_obj == NULL || irp == NULL)
        return STATUS_INVALID_PARAMETER;

    status = STATUS_SUCCESS;
    irp_stack = IoGetCurrentIrpStackLocation(irp);
    ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;

    pdev_ext = (PUMSS_PORT_DEV_EXT) pdev_obj->DeviceExtension;

    switch (irp_stack->MajorFunction)
    {
        case IRP_MJ_INTERNAL_DEVICE_CONTROL:
        {
            switch (ctrl_code)
            {
                case IOCTL_REGISTER_DRIVER:
                {
                    PCLASS_DRV_REG_INFO pcdri;
                    if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CLASS_DRV_REG_INFO))
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }

                    pcdri = irp->AssociatedIrp.SystemBuffer;
                    if (pcdri->fdo_driver == NULL || pcdri->add_device == NULL || pcdri->pnp_dispatch == NULL)
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }
                    pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext;
                    pdrvr_ext->class_driver_info.fdo_driver = pcdri->fdo_driver;
                    pdrvr_ext->class_driver_info.add_device = pcdri->add_device;
                    pdrvr_ext->class_driver_info.pnp_dispatch = pcdri->pnp_dispatch;
                    EXIT_DISPATCH(STATUS_SUCCESS, irp);
                }
                case IOCTL_REVOKE_DRIVER:
                {
                    pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext;
                    pdrvr_ext->class_driver_info.fdo_driver = NULL;
                    pdrvr_ext->class_driver_info.add_device = NULL;
                    pdrvr_ext->class_driver_info.pnp_dispatch = NULL;
                    EXIT_DISPATCH(STATUS_SUCCESS, irp);
                }
            }
        }
        case IRP_MJ_CREATE:
        case IRP_MJ_CLOSE:
        {
            EXIT_DISPATCH(STATUS_SUCCESS, irp);
        }
    }
    EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp);
}

BOOLEAN
umss_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_DEV_CAPABLE;
    pdriver->driver_desc.vendor_id = 0x0dd8;    // USB Vendor ID
    pdriver->driver_desc.product_id = 0x0003;   // 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 driver";       // Driver name for Name Registry
    pdriver->driver_desc.dev_class = USB_CLASS_MASS_STORAGE;
    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_connect;
    pdriver->disp_tbl.dev_disconnect = umss_disconnect;
    pdriver->disp_tbl.dev_stop = umss_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;
    }

    umss_load_class_driver(NULL);

    // umss_schedule_workitem( NULL, umss_load_class_driver, NULL, 0 );
    usb_dbg_print(DBGLVL_MAXIMUM, ("umss_driver_init(): umss driver is initialized\n"));
    return TRUE;
}

BOOLEAN
umss_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
    PUMSS_DRVR_EXTENSION pdrvr_ext;
    if (dev_mgr == NULL || pdriver == NULL)
        return FALSE;

    pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdriver->driver_ext;
    umss_delete_port_device(pdrvr_ext->port_dev_obj);
    pdrvr_ext->port_dev_obj = NULL;

    ASSERT(IsListEmpty(&pdrvr_ext->dev_list) == TRUE);
    usb_free_mem(pdriver->driver_ext);
    pdriver->driver_ext = NULL;
    pdriver->driver_ext_size = 0;
    usb_dbg_print(DBGLVL_MAXIMUM, ("umss_driver_destroy(): umss driver is destroyed\n"));
    return TRUE;
}

PDEVICE_OBJECT
umss_create_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER umss_drvr, DEV_HANDLE dev_handle, BOOLEAN is_if)
{

    CHAR dev_name[64], dev_id;
    STRING string;
    NTSTATUS status;
    PDEVICE_OBJECT pdev;
    UNICODE_STRING name_string, symb_link;
    PUMSS_DRVR_EXTENSION pdrvr_ext;
    PUMSS_DEVICE_EXTENSION pdev_ext;

    usb_dbg_print(DBGLVL_MAXIMUM, ("umss_create_device(): entering...\n"));
    pdrvr_ext = (PUMSS_DRVR_EXTENSION) umss_drvr->driver_ext;
    dev_id = (UCHAR) dev_id_from_handle(dev_handle);    // pdrvr_ext->dev_count;

    if (is_if == FALSE)
        sprintf(dev_name, "\\Device\\umssdev_%d", (int)dev_id);
    else
        sprintf(dev_name, "\\Device\\umssifdev_%d", (int)dev_id);

    RtlInitString(&string, dev_name);
    RtlAnsiStringToUnicodeString(&name_string, &string, TRUE);
    pdev = NULL;

    status = IoCreateDevice(dev_mgr->usb_driver_obj,
                            sizeof(UMSS_DEVICE_EXTENSION),
                            &name_string,
                            FILE_USB_DEV_TYPE,
                            0,
                            TRUE,
                            &pdev);

    if (status == STATUS_SUCCESS)
    {
        //
        // We do direct io
        //
        pdev->Flags |= DO_DIRECT_IO;

        pdev->Flags &= ~DO_DEVICE_INITIALIZING;
        pdev->StackSize = 2;    //one for fdo, one for file device obj

        pdev_ext = (PUMSS_DEVICE_EXTENSION) pdev->DeviceExtension;

        //may be accessed by other thread
        ExAcquireFastMutex(&pdrvr_ext->dev_list_mutex);
        InsertTailList(&pdrvr_ext->dev_list, &pdev_ext->dev_obj_link);
        pdrvr_ext->dev_count++;
        ExReleaseFastMutex(&pdrvr_ext->dev_list_mutex);

        if (is_if)
            pdev_ext->flags |= UMSS_DEV_FLAG_IF_DEV;

        pdev_ext->umss_dev_id = dev_id;
        pdev_ext->pdo = pdev;
        pdev_ext->dev_handle = dev_handle;
        pdev_ext->dev_mgr = dev_mgr;
        pdev_ext->pdriver = umss_drvr;

        pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_CLIENT_DEV;
        pdev_ext->dev_ext_hdr.dispatch = umss_dispatch_routine;
        pdev_ext->dev_ext_hdr.start_io = umss_start_io;
        pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr;

        if (is_if == FALSE)
            sprintf(dev_name, "\\DosDevices\\umssdev%d", (int)dev_id);
        else
            sprintf(dev_name, "\\DosDevices\\umssifdev%d", (int)dev_id);

        RtlInitString(&string, dev_name);
        RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
        IoCreateSymbolicLink(&symb_link, &name_string);
        RtlFreeUnicodeString(&symb_link);
        KeInitializeEvent(&pdev_ext->sync_event, SynchronizationEvent, FALSE);
        KeInitializeSpinLock(&pdev_ext->dev_lock);

    }
    RtlFreeUnicodeString(&name_string);
    return pdev;
}

BOOLEAN
umss_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle)

⌨️ 快捷键说明

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