none
Custom HID Device Driver - Reporting Mouse Data to System But No Pointer Movement (KMDF) RRS feed

  • Question

  • Hey all,

    Newbie here, I am writing a driver for a device that I want to use as a HID mouse/pointer and I am having some weird issues with reporting the mouse data to the system.  I started from the HidUsbFx2 sample driver and altered the code as necessary (ie. changed report descriptor and implemented other customized code).  My driver receives data from the device successfully but does not send the mouse input report to the system correctly.  From my debug print statements I can see that the driver is receiving accurate relative x,y data from the device.  I also see that the driver is sending data because the system continues to send read requests (after each time the driver sends new mouse data) but the pointer never moves.  My report descriptor looks alright to me and my mouse input report structure matches the descriptor.  I can't figure out what the problem is.  Does anyone have any thoughts on what could be causing this behavior?  

    I also want the device to function as a fake HID keyboard so that I can send keyboard shortcuts to the system or active application (eg. rotate, zoom, etc.).  Am I correct in thinking that I can accomplish this by including a keyboard TLC in my report descriptor, creating a keyboard input structure and reporting the key scan codes to the system under the report ID that I specified in my keyboard TLC?

    Thanks for your time.

    Thursday, July 11, 2013 5:28 PM

Answers

All replies

  • we need more info. you need to post your hid descriptor and code that reports the data. a byte by byte hex dump of a valid packet reported to hidclass would be helpful. you might need to include the report id in the reported packet.

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, July 11, 2013 8:02 PM
  • REPORT DESCRIPTOR:

    // Mouse Collection
        0x05, 0x01,                         // USAGE_PAGE (Generic Desktop)
        0x09, 0x02,                         // USAGE (Mouse)
        0xa1, 0x01,                         // COLLECTION (Application)
        0x85, REPORTID_MOUSE,    //   REPORT_ID (Mouse) (REPORTID_MOUSE = 0x01)
        0x09, 0x01,                         //   USAGE (Pointer)
        0xa1, 0x00,                         //   COLLECTION (Physical)
        0x05, 0x09,                         //     USAGE_PAGE (Button)
        0x19, 0x01,                         //     USAGE_MINIMUM (Button 1)
        0x29, 0x02,                         //     USAGE_MAXIMUM (Button 2)
        0x15, 0x00,                         //     LOGICAL_MINIMUM (0)
        0x25, 0x01,                         //     LOGICAL_MAXIMUM (1)
        0x75, 0x01,                         //     REPORT_SIZE (1)
        0x95, 0x02,                         //     REPORT_COUNT (2)
        0x81, 0x02,                         //     INPUT (Data,Var,Abs)
        0x95, 0x06,                         //     REPORT_COUNT (6)
        0x81, 0x03,                         //     INPUT (Cnst,Var,Abs)
        0x05, 0x01,                         //     USAGE_PAGE (Generic Desktop)
        0x09, 0x30,                         //     USAGE (X)
        0x09, 0x31,                         //     USAGE (Y)
        0x75, 0x10,                         //     REPORT_SIZE (16)
        0x95, 0x02,                         //     REPORT_COUNT (2)
        0x16, 0x01, 0x80,               //     LOGICAL_MINIMUM (-32767)
        0x26, 0xff, 0x7f,                  //     LOGICAL_MAXIMUM (32767)
        0x81, 0x02,                         //     INPUT (Data,Var,Abs)
        0xc0,                                   //   END_COLLECTION
        0xc0,                                   // END_COLLECTION

    MOUSE DATA INPUT STRUCTURE:

         typedef struct _HID_MOUSE_REPORT
         {
         UCHAR reportID;
         UCHAR buttons;
         SHORT xData;
         SHORT yData;
         }HID_MOUSE_REPORT, *PHID_MOUSE_REPORT;

    FUNCTION THAT REPORTS MOUSE DATA:

    VOID MouseReport(PDEVICE_EXTENSION devContext,GESTURE_DATA gestureData) 
    {
    PHID_MOUSE_REPORT report;
    NTSTATUS status;
    WDFREQUEST request;

    DbgPrint("MouseReport");

    status = WdfIoQueueRetrieveNextRequest(devContext->InterruptMsgQueue, &request);

    if(!NT_SUCCESS(status)){
    DbgPrint("WdfIoQueueRetrieveNextRequest failed with status: 0x%x\n",status);
    }else if (NT_SUCCESS(status)){
             //
            // IOCTL_HID_READ_REPORT is METHOD_NEITHER so WdfRequestRetrieveOutputBuffer
            // will correctly retrieve buffer from Irp->UserBuffer. Remember that
            // HIDCLASS provides the buffer in the Irp->UserBuffer field
            // irrespective of the ioctl buffer type. However, framework is very
            // strict about type checking. You cannot get Irp->UserBuffer by using
            // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER
            // internal ioctl.
            //

    status = WdfRequestRetrieveOutputBuffer(request,
                                                       sizeof(HID_MOUSE_REPORT),
                                                       &report,
                                                       NULL); //bufferLength

    if (!NT_SUCCESS(status)) {   // should never happen
    TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                    "WdfRequestRetrieveOutputBuffer failed with status: 0x%x\n", status);
    DbgPrint(("Retrieve error\n"));
    WdfRequestComplete(request, status);
    }else{
    // KdPrint(("mem size %d ", sizeof(HID_MOUSE_REPORT)));
    // memset(report, 0, sizeof(HID_MOUSE_REPORT));
    report->reportID = REPORTID_MOUSE;
    report->buttons = 0x00;
    report->xData = gestureData.tMotionData2D.lX;
    report->yData = (-1)*gestureData.tMotionData2D.lY;   // Device reports negated Y data for some reason

    DbgPrint(" rpID: %d, x: %d, y: %d, buttons: %d\n",report->reportID,gestureData.tMotionData2D.lX, (-1)*gestureData.tMotionData2D.lY,report->buttons);//report->ReportID,report->wXData,report->wYData); 

    WdfRequestComplete(request, status);
    }
    }
    }

    When I receive an "IOCTL_HID_READ_REPORT" request in my InternalDeviceControl function I forward the request to the appropriate queue with the following line of code (followed by the appropriate code to check for a failed forwarding attempt):

    status = WdfRequestForwardToIoQueue(Request, devContext->InterruptMsgQueue);

    Then, I call the MouseReport function from my EvtUsbInPipeReadComplete function (this is a function that is part of HidUsbFx2 sample code that I've made additions to in order to isolate the event in which I need to report the mouse data but the main functionality of this function is the same as the sample code).

    Follow up question:

    When I open device manager and look at the properties of my device to check what drivers have been loaded should hidclass be listed?  The only drivers listed there are my own and mshidkmdf.sys.  I guess I'm not sure how to get that dump for you. 

    Thursday, July 11, 2013 8:47 PM
  • hidclass will not be listed in device manager

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, July 11, 2013 9:00 PM
  • Okay, good to know about hidclass not being listed in device manager.  

    Any ideas on what's going on with reporting the mouse data?  Thanks for the replies by the way, I've been stuck on this for quite a while and I'm kind of on my own with this project as an intern so I really appreciate the info/help.

    Thursday, July 11, 2013 10:19 PM
  • as indicated in the NTDEV thread (http://www.osronline.com/showthread.cfm?link=245684 ), this

    WdfRequestComplete(request, status);

    should be

    WdfRequestCompleteWithInformation(request, status, sizeof(HID_MOUSE_REPORT));


    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Monday, July 15, 2013 9:08 PM