USB HID Touch

hi all,
we have a few questions related to HID touch.

  1. from the link http://msdn.microsoft.com/en-us/library/windows/hardware/jj128406(v=vs.85).aspx we come to know that there are no client mapper driver or a class driver for touch based HID devices. so what is the mechanism here involved with Touch reports ?

  2. we have a USB touch device which can be controlled by sending commands as part of USB HID reports to it at its USB OUT endpoint. So our idea was to implement IOCTL_HID_SET_OUTPUT_REPORT and if we want to read back the status of the command then we implement IOCTL_HID_GET_INPUT_REPORT.
    so thinking was to implement a filter driver which would take care of sending these IOCTLs. But since there are no client mapper driver/class driver as such for touch …we are a little confused as to where will the fliter driver ‘sit’. Or should we implement a seperate client mapper driver for our situation.there are two USB interfaces for the device: one for COntrol Reports and the other for Touch Reports, so can we have the client mapper driver installed only for the CONTROL interface ?

  3. and , is it possible to directly send these IOCTLs to HIDClass.sys ? because when tried to get IOTarget handle for HIDClass.sys we got a BSOD.

please let us know about these questions …it will help us in proceeding further …

thanks,

1 the os opens the hid TLC and reads hid reports directly
2 don’t mix your touch TLC with config and control. Put config and control in a separate TLC
3 you send Io to the raw pdo hidcass enumerates after you open a handle to the device, you cannot open a handle to the hidclass fdo.

d

dent from pjone


From: xxxxx@gmail.commailto:xxxxx
Sent: ?12/?1/?2012 10:22 AM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: [ntdev] USB HID Touch

hi all,
we have a few questions related to HID touch.

1. from the link http://msdn.microsoft.com/en-us/library/windows/hardware/jj128406(v=vs.85).aspx we come to know that there are no client mapper driver or a class driver for touch based HID devices. so what is the mechanism here involved with Touch reports ?

2. we have a USB touch device which can be controlled by sending commands as part of USB HID reports to it at its USB OUT endpoint. So our idea was to implement IOCTL_HID_SET_OUTPUT_REPORT and if we want to read back the status of the command then we implement IOCTL_HID_GET_INPUT_REPORT.
so thinking was to implement a filter driver which would take care of sending these IOCTLs. But since there are no client mapper driver/class driver as such for touch …we are a little confused as to where will the fliter driver ‘sit’. Or should we implement a seperate client mapper driver for our situation.there are two USB interfaces for the device: one for COntrol Reports and the other for Touch Reports, so can we have the client mapper driver installed only for the CONTROL interface ?

3. and , is it possible to directly send these IOCTLs to HIDClass.sys ? because when tried to get IOTarget handle for HIDClass.sys we got a BSOD.

please let us know about these questions …it will help us in proceeding further …

thanks,


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer</mailto:xxxxx></mailto:xxxxx>

hi Doran …
thanks for your reply …

  1. but why does OS do this only for touch and not for mouse/keyboard HID … is it related to performance ??
  2. config/control is a seperate TLC … so now should i have a client mapper driver on top of HIDClass or a filter driver on top of HidClass is required so that we can send IOCTL_HID_SET_OUTPUT_REPORT and IOCTL_HID_GET_INPUT_REPORT. we are not sure about the ‘filter driver implementation’ because there are no client drivers of touch that we can make a filter driver for… so how should we proceed.
  3. currently we are trying to load our driver as a filter driver on top of HIDclass for the CONTROL interface of the USB HID device, and then proceed with WdfIoTargetCreate, WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME, WdfIoTargetOpen, WdfIoTargetSendIoctlSynchronously() functions. But we are getting a BSOD… we are making a some mistake here but not able to know what …

1 mapped drivers for keyboard and mice exist because os suport for them existed since nt3.1 and we made the decision during win2k development to not update win32k to understand hid, so we created the mapper drivers to translate to what win32k understood. Nothing to do with perf. When touch came along, we wanted pure hid for the data (and win32k doesn’t do the reading btw) so no mappers

2 iirc those are ioctls you can send from user mode, no need to to even have a driver

3 post your code and the output of !analyze -v

d

dent from pjone


From: xxxxx@gmail.commailto:xxxxx
Sent: ?12/?1/?2012 6:27 PM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: RE:[ntdev] USB HID Touch

hi Doran …
thanks for your reply …

1. but why does OS do this only for touch and not for mouse/keyboard HID … is it related to performance ??
2. config/control is a seperate TLC … so now should i have a client mapper driver on top of HIDClass or a filter driver on top of HidClass is required so that we can send IOCTL_HID_SET_OUTPUT_REPORT and IOCTL_HID_GET_INPUT_REPORT. we are not sure about the ‘filter driver implementation’ because there are no client drivers of touch that we can make a filter driver for… so how should we proceed.
3. currently we are trying to load our driver as a filter driver on top of HIDclass for the CONTROL interface of the USB HID device, and then proceed with WdfIoTargetCreate, WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME, WdfIoTargetOpen, WdfIoTargetSendIoctlSynchronously() functions. But we are getting a BSOD… we are making a some mistake here but not able to know what …


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer</mailto:xxxxx></mailto:xxxxx>

hi doran,

  1. got some idea … will do further reading on that…
  2. yes …but our requirement from the client is for a filter driver which can control the USB HID Touch device. Hence our method of implementing a filter driver.
  3. we have removed the BSOD and currently we are getting the handle to the IOTarget Device but not able to Open the device …throws up an error : 0xC000000E.[NO_SUCH_DEVICE].
    i have attached the code below … please let us know if we have something wrong in our implementation. We have taken Firefly USB Client Upper Filter Driver as a reference. Modified its inf file to include input.inf so that we will have hidclass.sys, hidusb.sys and hidparse.sys.
    On the device connected to PC, it enumerates with two USB HID interfaces. We load our driver for the HID control interface via Device Manager.
    Below is the code,

    #ifdef ENABLE_HID_IO
    NTSTATUS
    test_func_get_collec(WDFDEVICE device,
    PDEVICE_CONTEXT pDeviceContext
    )
    {
    //send HID ioctls to our device
    //IOCTLs will be handled by HIDUSB and converted into USB requests

    WDFIOTARGET hidTarget = NULL;
    NTSTATUS status = STATUS_SUCCESS;
    WDF_IO_TARGET_OPEN_PARAMS openParams;
    WDF_MEMORY_DESCRIPTOR outputDescriptor;
    HID_COLLECTION_INFORMATION collectionInformation = {0};

    //create IOTarget
    KdPrint((“test_func_get_collec: create IOTarget\n”));

    status = WdfIoTargetCreate(device,
    WDF_NO_OBJECT_ATTRIBUTES,
    &hidTarget);
    if (!NT_SUCCESS(status))
    {
    KdPrint((“test_func_get_collec: WdfIoTargetCreate failed 0x%x\n”, status));
    return status;
    }

    WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(
    &openParams,
    &pDeviceContext->PdoName,
    FILE_WRITE_ACCESS);

    openParams.ShareAccess = FILE_SHARE_WRITE | FILE_SHARE_READ;

    //Open the target
    KdPrint((“test_func_get_collec: open IOTarget\n”));

    status = WdfIoTargetOpen(hidTarget, &openParams);
    if (!NT_SUCCESS(status)) {
    KdPrint((“test_func_get_collec: WdfIoTargetOpen failed 0x%x\n”, status));
    return status;
    }

    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputDescriptor,
    (PVOID) &collectionInformation,
    sizeof(HID_COLLECTION_INFORMATION));

    //send IOCTL
    KdPrint((“test_func_get_collec: send IOCTL\n”));

    status = WdfIoTargetSendIoctlSynchronously(hidTarget,
    NULL,
    IOCTL_HID_GET_COLLECTION_INFORMATION,
    NULL,
    &outputDescriptor,
    NULL,
    NULL);

    if (!NT_SUCCESS(status)) {
    KdPrint((“test_func_get_collec: WdfIoTargetSendIoctlSynchronously failed 0x%x\n”, status));
    return status;
    }

    KdPrint((“test_func_get_collec: collectionInformation:0x%x\n”, collectionInformation.DescriptorSize));
    KdPrint((“test_func_get_collec: collectionInformation:0x%x\n”, collectionInformation.Polled));
    KdPrint((“test_func_get_collec: collectionInformation:0x%x\n”, collectionInformation.ProductID));
    KdPrint((“test_func_get_collec: collectionInformation:0x%x\n”, collectionInformation.VendorID));
    KdPrint((“test_func_get_collec: collectionInformation:0x%x\n”, collectionInformation.VersionNumber));

    return status;
    }

    #endif

    NTSTATUS
    FireFlyEvtDeviceAdd(
    WDFDRIVER Driver,
    PWDFDEVICE_INIT DeviceInit
    )
    /++
    Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager. We create and initialize a device object to
    represent to be part of the device stack as a filter.

    Arguments:

    Driver - Handle to a framework driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

    Return Value:

    NTSTATUS

    /
    {
    WDF_OBJECT_ATTRIBUTES attributes;
    NTSTATUS status;
    PDEVICE_CONTEXT pDeviceContext;
    WDFDEVICE device;
    WDFMEMORY memory;
    size_t bufferLength;

    PDEVICE_OBJECT pnext_obj = NULL;
    PDEVICE_OBJECT pcurrent_obj = NULL;

    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE();

    //
    // Configure the device as a filter driver
    //
    WdfFdoInitSetFilter(DeviceInit);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if (!NT_SUCCESS(status)) {
    KdPrint((“FireFly: WdfDeviceCreate, Error %x\n”, status));
    return status;
    }
    #ifdef ENABLE_HID_IO
    KdPrint((“======================Firefly Original=======================\n”));
    KdPrint((“FireFlyEvtDeviceAdd: WdfDeviceCreate: wdfdevice: 0x%x\n”,device));
    pcurrent_obj = WdfDeviceWdmGetDeviceObject(device);
    KdPrint((“FireFlyEvtDeviceAdd: WdfDeviceCreate: pdev_obj: 0x%x\n”,pcurrent_obj));
    if(pcurrent_obj)
    {
    KdPrint((“FireFlyEvtDeviceAdd: AttachedDevice: 0x%x\n”,pcurrent_obj->AttachedDevice));
    KdPrint((“FireFlyEvtDeviceAdd: NextDevice: 0x%x\n”,pcurrent_obj->NextDevice));
    KdPrint((“FireFlyEvtDeviceAdd: DeviceType: 0x%x\n”,pcurrent_obj->DeviceType));
    KdPrint((“FireFlyEvtDeviceAdd: : Characteristics: 0x%x\n”,pcurrent_obj->Characteristics));
    KdPrint((“FireFlyEvtDeviceAdd: : AttachedTo: 0x%x\n”,pcurrent_obj->DeviceObjectExtension->AttachedTo));
    KdPrint((“FireFlyEvtDeviceAdd: : owning_device_object: 0x%x\n”,pcurrent_obj->DeviceObjectExtension->DeviceObject));
    KdPrint((“FireFlyEvtDeviceAdd: : Type: 0x%x\n”,pcurrent_obj->DeviceObjectExtension->Type));
    }

    pnext_obj = WdfDeviceWdmGetAttachedDevice(device);
    KdPrint((“FireFlyEvtDeviceAdd: : pnext_obj: 0x%x\n”,pnext_obj));
    KdPrint((“================================================================\n”));
    #endif
    //
    // Driver Framework always zero initializes an objects context memory
    //
    pDeviceContext = WdfObjectGet_DEVICE_CONTEXT(device);

    //
    // Initialize our WMI support
    //
    status = WmiInitialize(device, pDeviceContext);
    if (!NT_SUCCESS(status)) {
    KdPrint((“FireFly: Error initializing WMI 0x%x\n”, status));
    return status;
    }

    //
    // In order to send ioctls to our PDO, we have open to open it
    // by name so that we have a valid filehandle (fileobject).
    // When we send ioctls using the IoTarget, framework automatically
    // sets the filobject in the stack location.
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    //
    // By parenting it to device, we don’t have to worry about
    // deleting explicitly. It will be deleted along witht the device.
    //
    attributes.ParentObject = device;

    status = WdfDeviceAllocAndQueryProperty(device,
    DevicePropertyPhysicalDeviceObjectName,
    NonPagedPool,
    &attributes,
    &memory);

    if (!NT_SUCCESS(status)) {
    KdPrint((“FireFly: WdfDeviceAllocAndQueryProperty failed 0x%x\n”, status));
    return STATUS_UNSUCCESSFUL;
    }

    pDeviceContext->PdoName.Buffer = WdfMemoryGetBuffer(memory, &bufferLength);

    if (pDeviceContext->PdoName.Buffer == NULL) {
    return STATUS_UNSUCCESSFUL;
    }

    pDeviceContext->PdoName.MaximumLength = (USHORT) bufferLength;
    pDeviceContext->PdoName.Length = (USHORT) bufferLength-sizeof(UNICODE_NULL);

    #ifdef ENABLE_HID_IO
    //try to initiate IOCTL
    test_func_get_collec(device,pDeviceContext);
    #endif

    return status;
    }

    please let us know if anything wrong in our implementation,

    thanks,

Tell your client they don’t need a driver. You could easily do the same thing with a service or per user app. You can’t open a handle to your own stack in adddevjce, the stack needs to be fully started to open a handle.

d

dent from pjone


From: xxxxx@gmail.commailto:xxxxx
Sent: ?12/?2/?2012 6:49 AM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: RE:[ntdev] USB HID Touch

hi doran,
1. got some idea … will do further reading on that…
2. yes …but our requirement from the client is for a filter driver which can control the USB HID Touch device. Hence our method of implementing a filter driver.
3. we have removed the BSOD and currently we are getting the handle to the IOTarget Device but not able to Open the device …throws up an error : 0xC000000E.[NO_SUCH_DEVICE].
i have attached the code below … please let us know if we have something wrong in our implementation. We have taken Firefly USB Client Upper Filter Driver as a reference. Modified its inf file to include input.inf so that we will have hidclass.sys, hidusb.sys and hidparse.sys.
On the device connected to PC, it enumerates with two USB HID interfaces. We load our driver for the HID control interface via Device Manager.
Below is the code,

#ifdef ENABLE_HID_IO
NTSTATUS
test_func_get_collec(WDFDEVICE device,
PDEVICE_CONTEXT pDeviceContext
)
{
//send HID ioctls to our device
//IOCTLs will be handled by HIDUSB and converted into USB requests

WDFIOTARGET hidTarget = NULL;
NTSTATUS status = STATUS_SUCCESS;
WDF_IO_TARGET_OPEN_PARAMS openParams;
WDF_MEMORY_DESCRIPTOR outputDescriptor;
HID_COLLECTION_INFORMATION collectionInformation = {0};

//create IOTarget
KdPrint((“test_func_get_collec: create IOTarget\n”));

status = WdfIoTargetCreate(device,
WDF_NO_OBJECT_ATTRIBUTES,
&hidTarget);
if (!NT_SUCCESS(status))
{
KdPrint((“test_func_get_collec: WdfIoTargetCreate failed 0x%x\n”, status));
return status;
}

WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(
&openParams,
&pDeviceContext->PdoName,
FILE_WRITE_ACCESS);

openParams.ShareAccess = FILE_SHARE_WRITE | FILE_SHARE_READ;

//Open the target
KdPrint((“test_func_get_collec: open IOTarget\n”));

status = WdfIoTargetOpen(hidTarget, &openParams);
if (!NT_SUCCESS(status)) {
KdPrint((“test_func_get_collec: WdfIoTargetOpen failed 0x%x\n”, status));
return status;
}

WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputDescriptor,
(PVOID) &collectionInformation,
sizeof(HID_COLLECTION_INFORMATION));

//send IOCTL
KdPrint((“test_func_get_collec: send IOCTL\n”));

status = WdfIoTargetSendIoctlSynchronously(hidTarget,
NULL,
IOCTL_HID_GET_COLLECTION_INFORMATION,
NULL,
&outputDescriptor,
NULL,
NULL);

if (!NT_SUCCESS(status)) {
KdPrint((“test_func_get_collec: WdfIoTargetSendIoctlSynchronously failed 0x%x\n”, status));
return status;
}

KdPrint((“test_func_get_collec: collectionInformation:0x%x\n”, collectionInformation.DescriptorSize));
KdPrint((“test_func_get_collec: collectionInformation:0x%x\n”, collectionInformation.Polled));
KdPrint((“test_func_get_collec: collectionInformation:0x%x\n”, collectionInformation.ProductID));
KdPrint((“test_func_get_collec: collectionInformation:0x%x\n”, collectionInformation.VendorID));
KdPrint((“test_func_get_collec: collectionInformation:0x%x\n”, collectionInformation.VersionNumber));

return status;
}

#endif

NTSTATUS
FireFlyEvtDeviceAdd(
WDFDRIVER Driver,
PWDFDEVICE_INIT DeviceInit
)
/++
Routine Description:

EvtDeviceAdd is called by the framework in response to AddDevice
call from the PnP manager. We create and initialize a device object to
represent to be part of the device stack as a filter.

Arguments:

Driver - Handle to a framework driver object created in DriverEntry

DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

NTSTATUS

/
{
WDF_OBJECT_ATTRIBUTES attributes;
NTSTATUS status;
PDEVICE_CONTEXT pDeviceContext;
WDFDEVICE device;
WDFMEMORY memory;
size_t bufferLength;

PDEVICE_OBJECT pnext_obj = NULL;
PDEVICE_OBJECT pcurrent_obj = NULL;

UNREFERENCED_PARAMETER(Driver);

PAGED_CODE();

//
// Configure the device as a filter driver
//
WdfFdoInitSetFilter(DeviceInit);

WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
if (!NT_SUCCESS(status)) {
KdPrint((“FireFly: WdfDeviceCreate, Error %x\n”, status));
return status;
}
#ifdef ENABLE_HID_IO
KdPrint((“======================Firefly Original=======================\n”));
KdPrint((“FireFlyEvtDeviceAdd: WdfDeviceCreate: wdfdevice: 0x%x\n”,device));
pcurrent_obj = WdfDeviceWdmGetDeviceObject(device);
KdPrint((“FireFlyEvtDeviceAdd: WdfDeviceCreate: pdev_obj: 0x%x\n”,pcurrent_obj));
if(pcurrent_obj)
{
KdPrint((“FireFlyEvtDeviceAdd: AttachedDevice: 0x%x\n”,pcurrent_obj->AttachedDevice));
KdPrint((“FireFlyEvtDeviceAdd: NextDevice: 0x%x\n”,pcurrent_obj->NextDevice));
KdPrint((“FireFlyEvtDeviceAdd: DeviceType: 0x%x\n”,pcurrent_obj->DeviceType));
KdPrint((“FireFlyEvtDeviceAdd: : Characteristics: 0x%x\n”,pcurrent_obj->Characteristics));
KdPrint((“FireFlyEvtDeviceAdd: : AttachedTo: 0x%x\n”,pcurrent_obj->DeviceObjectExtension->AttachedTo));
KdPrint((“FireFlyEvtDeviceAdd: : owning_device_object: 0x%x\n”,pcurrent_obj->DeviceObjectExtension->DeviceObject));
KdPrint((“FireFlyEvtDeviceAdd: : Type: 0x%x\n”,pcurrent_obj->DeviceObjectExtension->Type));
}

pnext_obj = WdfDeviceWdmGetAttachedDevice(device);
KdPrint((“FireFlyEvtDeviceAdd: : pnext_obj: 0x%x\n”,pnext_obj));
KdPrint((“================================================================\n”));
#endif
//
// Driver Framework always zero initializes an objects context memory
//
pDeviceContext = WdfObjectGet_DEVICE_CONTEXT(device);

//
// Initialize our WMI support
//
status = WmiInitialize(device, pDeviceContext);
if (!NT_SUCCESS(status)) {
KdPrint((“FireFly: Error initializing WMI 0x%x\n”, status));
return status;
}

//
// In order to send ioctls to our PDO, we have open to open it
// by name so that we have a valid filehandle (fileobject).
// When we send ioctls using the IoTarget, framework automatically
// sets the filobject in the stack location.
//
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
//
// By parenting it to device, we don’t have to worry about
// deleting explicitly. It will be deleted along witht the device.
//
attributes.ParentObject = device;

status = WdfDeviceAllocAndQueryProperty(device,
DevicePropertyPhysicalDeviceObjectName,
NonPagedPool,
&attributes,
&memory);

if (!NT_SUCCESS(status)) {
KdPrint((“FireFly: WdfDeviceAllocAndQueryProperty failed 0x%x\n”, status));
return STATUS_UNSUCCESSFUL;
}

pDeviceContext->PdoName.Buffer = WdfMemoryGetBuffer(memory, &bufferLength);

if (pDeviceContext->PdoName.Buffer == NULL) {
return STATUS_UNSUCCESSFUL;
}

pDeviceContext->PdoName.MaximumLength = (USHORT) bufferLength;
pDeviceContext->PdoName.Length = (USHORT) bufferLength-sizeof(UNICODE_NULL);

#ifdef ENABLE_HID_IO
//try to initiate IOCTL
test_func_get_collec(device,pDeviceContext);
#endif

return status;
}

please let us know if anything wrong in our implementation,

thanks,


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer</mailto:xxxxx></mailto:xxxxx>

hi doran …

the requirement for a driver from client seems to be a valid one because their requirement is as follows.

  1. get lid close/open events.
    2.on lid closure, disable USB HID touch<ioctl_hid_set_output_report>.
    3. on lid open, enable USB HID touch

    our understanding was that this should be done at driver level. but according to your statement may be our understanding is wrong … is there absolutely no way to proceed with our implementation?

    please provide your suggestion … its really useful.

    thanks,
    shreenivasa</ioctl_hid_set_output_report>