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

📄 hid.cpp

📁 pci 底层驱动
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        dbgLogTrace(("IOCTL_HID_READ_REPORT\n"));
        ntStatus = readReport(p_irp);
        break;

    case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
        dbgLogTrace(("IOCTL_GET_DEVICE_ATTRIBUTES\n"));
        ntStatus = getAttributes(p_irp);
        break;

    case IOCTL_HID_ACTIVATE_DEVICE:     //First open of a device
    case IOCTL_HID_DEACTIVATE_DEVICE:   //Last close of a device
    case IOCTL_HID_WRITE_REPORT:        //We only handle reads    

        ntStatus = STATUS_SUCCESS;
        break;

    case IOCTL_HID_GET_STRING:
    case IOCTL_HID_GET_FEATURE:
    case IOCTL_HID_SET_FEATURE:
    case IOCTL_GET_PHYSICAL_DESCRIPTOR:
    default:
        dbgLogError(("Unknown or unsupported IOCTL (%x)\n", 
            IrpStack->Parameters.DeviceIoControl.IoControlCode));
        ntStatus = STATUS_NOT_SUPPORTED;
        break;

    }         


    // Set return status in Irp
    p_irp->IoStatus.Status = ntStatus;

    // Complete Irp
    if (ntStatus != STATUS_PENDING)
    {
        IoCompleteRequest(p_irp, IO_NO_INCREMENT);
    }
    else
    {
        IoMarkIrpPending(p_irp);
    }

    dbgLogInfo(("HidMiniIoctl Exit = %x\n", ntStatus));

    return ntStatus;

}

/////////////////////////////////////////////////////////////////////////////////////////
//HidProcessing::getHidDescriptor
//
// This is the handler for IOCTL_HID_GET_DEVICE_DESCRIPTOR.  It copies our HID descriptor
// into the user's buffer.
//

NTSTATUS HidProcessing::getHidDescriptor(PIRP p_irp)
{
    PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(p_irp);
    dbgLogTrace(("HIDCLASS Buffer = 0x%x, Buffer length = 0x%x\n", 
        p_irp->UserBuffer, 
        IrpStack->Parameters.DeviceIoControl.OutputBufferLength));

    ULONG bytesToCopy = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;

    if (bytesToCopy > _s_hid_descriptor.bLength)
    {
        bytesToCopy = _s_hid_descriptor.bLength;
    }


    dbgLogTrace(("Copying %d bytes to HIDCLASS buffer\n", bytesToCopy));

    RtlCopyMemory(
        (PUCHAR) p_irp->UserBuffer, 
        (PUCHAR) &_s_hid_descriptor, 
        bytesToCopy);

    // Report how many bytes were copied
    p_irp->IoStatus.Information = bytesToCopy;

    return STATUS_SUCCESS;
}

/////////////////////////////////////////////////////////////////////////////////////////
//HidProcessing::getReportDescriptor
//
// Copies our report descriptor into the buffer in the IRP.  This is the handler for
// IOCTL_HID_GET_REPORT_DESCRIPTOR
//

NTSTATUS HidProcessing::getReportDescriptor(PIRP p_irp)
{
    PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(p_irp);
    dbgLogTrace(("HIDCLASS Buffer = 0x%x, Buffer length = 0x%x\n", 
        p_irp->UserBuffer, 
        IrpStack->Parameters.DeviceIoControl.OutputBufferLength));

    ULONG bytesToCopy = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;

    if (bytesToCopy > _s_hid_descriptor.wReportLength)
    {
        bytesToCopy = _s_hid_descriptor.wReportLength;
    }

    dbgLogTrace(("Copying %d bytes to HIDCLASS buffer\n", bytesToCopy));

    RtlCopyMemory((PUCHAR) p_irp->UserBuffer, (PUCHAR) _s_report_descriptor, bytesToCopy);

    // Report how many bytes were copied
    p_irp->IoStatus.Information = bytesToCopy;

    return STATUS_SUCCESS;
}

/////////////////////////////////////////////////////////////////////////////////////////
//HidProcessing::getAttributes
//
// This is the routine for processing IOCTL_HID_GET_DEVICE_ATTRIBUTES.  It just returns 
// the vendor and product ID's.
//
NTSTATUS HidProcessing::getAttributes(PIRP p_irp)
{
    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(p_irp);

    PHID_DEVICE_ATTRIBUTES deviceAttributes = 
        (PHID_DEVICE_ATTRIBUTES) p_irp->UserBuffer;

    ASSERT (sizeof (HID_DEVICE_ATTRIBUTES) ==
            irpStack->Parameters.DeviceIoControl.OutputBufferLength);

    // Report how many bytes were copied
    p_irp->IoStatus.Information = sizeof (HID_DEVICE_ATTRIBUTES);

    deviceAttributes->Size = sizeof (HID_DEVICE_ATTRIBUTES);
    deviceAttributes->VendorID = HIDMINI_VID;
    deviceAttributes->ProductID = HIDMINI_PID;
    deviceAttributes->VersionNumber = HIDMINI_VERSION;

    return STATUS_SUCCESS;
}

/////////////////////////////////////////////////////////////////////////////////////////
//HidProcessing::readReport
//
// This is the function for processing IOCTL_HID_READ_REPORT.  This function puts the 
// report on its IRP list to be removed and completed when there is a keystroke available.
//
NTSTATUS HidProcessing::readReport(PIRP p_irp)
{
    PVOID ReportBuffer = p_irp->UserBuffer;
    PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(p_irp);
    ULONG ReportTotalSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
    
    dbgLogTrace(("ReportBuffer = 0x%x, ReportTotalSize = 0x%x\n", ReportBuffer, ReportTotalSize));
    
    if (ReportTotalSize && ReportBuffer)
    {
        //  Increase the count of outstanding IOs.
        _request_count.increment();
        
        //Save our object in case the IRP gets canceled
        p_irp->Tail.Overlay.DriverContext[0] = this;
        
        //Put the IRP on the read list.
        _irp_list.add(p_irp);
        
        //Mark the IRP as cancelable
        KIRQL old_irql;
        IoAcquireCancelSpinLock(&old_irql);
        IoSetCancelRoutine(p_irp, static_readReportCancel);
        IoReleaseCancelSpinLock(old_irql);    
        
        return STATUS_PENDING;
    }
    else
    {
        // No buffer, or buffer of zero size
        return STATUS_INVALID_PARAMETER;
    }
}

/////////////////////////////////////////////////////////////////////////////////////////
//HidProcessing::submitReport
//
// This is a public function called from outside the class when a keystroke is detected
// and the driver needs to notify Windows of it.
//
// p_report - Pointer to the report structure
// report_size - Size of the report structure
//
// There are currently only two types of reports in use, KEYBOARD_USAGE_PAGE_REPORT for
// putting keys in the keyboard buffer, or CONSUMER_USAGE_PAGE_REPORT for generating 
// AppCommands.  This is a generic function that can send any type of report to the 
// system.
//
VOID HidProcessing::submitReport(PVOID p_report, ULONG report_size)
{
    //Get an IRP from the read report list
    PIRP p_irp = _irp_list.remove();
    if(p_irp)
    {
        //Take the cancel routine off the IRP
        KIRQL old_irql;
        IoAcquireCancelSpinLock(&old_irql);
        PDRIVER_CANCEL p_cancel = IoSetCancelRoutine(p_irp, NULL);
        IoReleaseCancelSpinLock(old_irql);    
        
        if(!p_cancel)
        {
            //IRP was cancelled
            return;
        }
        
        //make sure the buffer is big enough
        PIO_STACK_LOCATION p_irp_stack = IoGetCurrentIrpStackLocation(p_irp);
        ULONG buffer_size = 
            p_irp_stack->Parameters.DeviceIoControl.OutputBufferLength;

        if(buffer_size >= report_size)
        {                
            p_irp->IoStatus.Status = STATUS_SUCCESS;
            p_irp->IoStatus.Information = report_size;
            RtlCopyMemory(p_irp->UserBuffer, p_report, report_size);            
        }
        else
        {
            p_irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
            p_irp->IoStatus.Information = 0;
        }

        IoCompleteRequest(p_irp, IO_NO_INCREMENT);
        _request_count.decrement();
   }

}

/////////////////////////////////////////////////////////////////////////////////////////
//HidProcessing::cancelOutstandingRequests
//
// Cancels all read report IRPs in our queue.
//
VOID HidProcessing::cancelOutstandingRequests()
{
    PIRP p_irp = _irp_list.remove();
    while(p_irp)
    {
        //Take the cancel routine off the IRP
        KIRQL old_irql;
        IoAcquireCancelSpinLock(&old_irql);
        PDRIVER_CANCEL p_cancel = IoSetCancelRoutine(p_irp, NULL);
        IoReleaseCancelSpinLock(old_irql);    

        if(p_cancel)
        {
            //Only complete the request here if the IRP wasn't already canceled
            p_irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
            IoCompleteRequest(p_irp, IO_NO_INCREMENT);
            _request_count.decrement();
        }

        p_irp = _irp_list.remove();
    }
}

/////////////////////////////////////////////////////////////////////////////////////////
//HidProcessing::cancelReadReport
//
// Cancel a read report in our queue.  HidProcessing holds read reports in a cancelable 
// state.  This is a typical IRP cancel routine.  
//
VOID HidProcessing::cancelReadReport(PIRP p_irp)
{
    p_irp->IoStatus.Status = STATUS_CANCELLED;

    //Remove the IRP from the queue
    _irp_list.remove(p_irp);

    //Drop the cancel spinlock
    IoReleaseCancelSpinLock(p_irp->CancelIrql);

    //Complete the IRP
    p_irp->IoStatus.Information = 0;
    IoCompleteRequest(p_irp, IO_NO_INCREMENT);

    //Decrement the request count);
    _request_count.decrement();
}

/////////////////////////////////////////////////////////////////////////////////////////
//HidProcessing::static_readReportCancel
//
//This is called to cancel a read report IRP. This is the static DDK entry point.  It 
// just calls the non-static cancelReadReport.
//
VOID HidProcessing::static_readReportCancel(
    PDEVICE_OBJECT DeviceObject,
    PIRP p_irp)
{
    HidProcessing* p_this =
        (HidProcessing*) p_irp->Tail.Overlay.DriverContext[0];

   p_this->cancelReadReport(p_irp);
}

/////////////////////////////////////////////////////////////////////////////////////////
//HidProcessing::~HidProcessing (destructer)
//
// Make sure we aren't holding and HID read report requests before we exit.
//
HidProcessing::~HidProcessing()
{
    //Make sure we aren't holding any read reports
    cancelOutstandingRequests();
    _request_count.wait();
}

⌨️ 快捷键说明

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