Driver installs using devcon but not using devmgr

I can now use devcon to install the revised inf file that delegates the HID driver installation to input.inf. That’s excellent!

devcon update lectouch.inf "USB\VID_05FF&PID_002A"

perdrix.co.uk/logs/setupapi.dev.20211203-09-39.log

Though when I look at the installed driver using devmgr afterwards, I see:

Showing TWO HID devices! Is that normal when a filter driver is installed? There were two hardware initiated driver install event s in the log after the devcon install of the driver

Sadly the “normal” way of doing it using devmgr (drilling down by connection and trying to update the base USB device) doesn’t work, saying the best driver is already installed.

It would seem that devmgr doesn’t like to select unsigned drivers :frowning: (and from what I read in the Oney book it doesn’t like to install filter drivers for devices that are already installed).

Is there any way to get this to install from devmgr that I’ve missed?

I don’t think it’s likely this will ever get signed as I’m surely not going to pony up for a EV Software Installation Certificate.

David

I think I may have worked why the extra device is there. If I uninstalled and deleted the driver, and then scan for hardware changes, the sections used to install the basic HID device were the Raw_Inst variants. Trying that now.

No, that didn’t work - it installed but the touch screen didn’t work!

David

Additional information: installing by using devcon install (instead of update) … did NOT work, or more specifically the install worked but the driver refused to start.

devcon install creates a virtual root enumerated device. For your problem you NEVER want to use devcon install. This is probably why you are seeing duplicate/extra HID devices in device manager.

For the question of two child HID compliant devices, the number of children is defined by the number of top level collections (TLCs) you define in your hid descriptor. It is 1:1. Since you are trying to expose a touch screen, one of the TLCs will need to be an absolute pointing device (IIRC) so that the hid mouse stack loads on the child device. You will see a different compatible ID and device name when the mouse stack is installed.

This exposes as a “Tablet Device” rather than a “Mouse Device”. But other than that …

So you’re saying there’s nothing to worry about with the extra device?

D.

Does your HID descriptor define two TLCs? If so, then two children is expected. If the number of enumerated children != number of TLCs then you have to investigate.

Here’s the descriptor:

HID_REPORT_DESCRIPTOR       G_DefaultReportDescriptor[] = {
    0x05, 0x0d,                         // USAGE_PAGE (Digitizers)
    0x09, 0x04,                         // USAGE (Touch Screen)
    0xa1, 0x01,                         // COLLECTION (Application)
    0x85, REPORTID_TOUCH,               //   REPORT_ID (Touch)
    0x09, 0x20,                         //   USAGE (Stylus)
    0xa1, 0x00,                         //   COLLECTION (Physical)
    0x09, 0x42,                         //     USAGE (Tip Switch)
    0x09, 0x32,                         //     USAGE (In Range)
    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,Ary,Abs)
    0x05, 0x01,                         //     USAGE_PAGE (Generic Desktop)
    0x09, 0x30,                         //     USAGE (X)
    0x09, 0x31,                         //     USAGE (Y)
    0x15, 0x00,                         //     LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x03,                   //     LOGICAL_MAXIMUM (1023)
    0x75, 0x10,                         //     REPORT_SIZE (16)
    0x95, 0x02,                         //     REPORT_COUNT (2)
    0x81, 0x02,                         //     INPUT (Data,Var,Abs)
    0xc0,                               //   END_COLLECTION
    0xc0,                               // END_COLLECTION
};

So I think that makes only one top level collection. However that’s appended to the existing URB:

    case URB_FUNCTION_CONTROL_TRANSFER:
    {
        struct _URB_CONTROL_TRANSFER* pTransfer = (struct _URB_CONTROL_TRANSFER*) pUrb;

        DbgPrint("pDescriptorRequest->TransferBufferLength = %d\n", pTransfer->TransferBufferLength);

        if (pTransfer->SetupPacket[0] == 0x80 && pTransfer->SetupPacket[1] == 0x06 &&
                pTransfer->SetupPacket[2] == 0x00 && pTransfer->SetupPacket[3] == 0x02 &&
                pTransfer->SetupPacket[4] == 0x00 && pTransfer->SetupPacket[5] == 0x00 &&
                pTransfer->SetupPacket[6] == 0x22 && pTransfer->SetupPacket[7] == 0x00) {
            // Configuration Descriptor
            PUCHAR buf = (PUCHAR)USBPcapURBGetBufferPointer(pTransfer->TransferBufferLength,
                pTransfer->TransferBuffer, pTransfer->TransferBufferMDL);

            size_t length = ((size_t)buf[0x1a] << 8) | (size_t)buf[0x19];
            length += sizeof(G_DefaultReportDescriptor); // Append to existing report descriptor.

            buf[0x1a] = (UCHAR)(length >> 8);
            buf[0x19] = (UCHAR)(length & 0xFF);
        }
        else if (pTransfer->SetupPacket[0] == 0x81 && pTransfer->SetupPacket[1] == 0x06 &&
                pTransfer->SetupPacket[2] == 0x00 && pTransfer->SetupPacket[3] == 0x22 &&
                pTransfer->SetupPacket[4] == 0x00 && pTransfer->SetupPacket[5] == 0x00)
		{
            // HID Report Descriptor
            // NOTE: Reallocating TransferBuffer is useless because it's a pointer provided by the upper driver.
            // But since we reported a sizeof(G_DefaultReportDescriptor) length, it should be allocated the right size.
            // Only the lower USB driver set TransferBufferLength back to 241, the original Report Descriptor size, which can be misleading.

			PUCHAR buf = NULL;
			
            size_t append_size = ((size_t)pTransfer->SetupPacket[7] << 8) | (size_t)pTransfer->SetupPacket[6];
            if (append_size > sizeof(G_DefaultReportDescriptor)) {
                append_size = sizeof(G_DefaultReportDescriptor);
            }

            buf = (PUCHAR)USBPcapURBGetBufferPointer(pTransfer->TransferBufferLength,
                pTransfer->TransferBuffer, pTransfer->TransferBufferMDL);

            RtlCopyMemory(&buf[pTransfer->TransferBufferLength], &G_DefaultReportDescriptor[0], append_size);
            pTransfer->TransferBufferLength += append_size;
        }

        break;
    }

David