tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Reading I2C HID descriptor from userland
Hello
I have a ihidev device that fails to find its HID descriptor. In order to
debug that, I try to retreive it from userspace.
At kernel boot, I have:
ihidev1 at iic2 addr 0x5d
I try the code at the end of this message, inspired from sys/dec/i2c/ihidev.c.
I am supposed to find the HID descriptor at address sc_hid_desc_addr, which
should come frome ACPI.
The HID over I2C specification is at https://docs.microsoft.com/en-us/previous-versions/windows/hardware/design/dn642101%28v=vs.85%29?redirectedfrom=MSDN
Section 10 deals with ACPI bindings. It says the HID descriptor
address is to be find in a _DSM object that "defines a structure
that contains the HID Descriptor address (2 bytes)"
acpdump -dt gives me this:
Method (_DSM, 4, Serialized) // _DSM: Device-Specific Method
{
If ((Arg0 == HIDG))
{
Return (HIDD (Arg0, Arg1, Arg2, Arg3, HID2))
}
Return (Buffer (One)
{
0x00 // .
})
}
How should this be readen? I found the HIDG definition earlier in the
ACPI dump, and my device has Name (HID2, One).
Name (HIDG, ToUUID ("3cdff6f7-4267-4555-ad05-b30a3d8938de") /* HID I2C Device */)
(...)
Method (HIDD, 5, Serialized)
{
If ((Arg0 == HIDG))
{
If ((Arg2 == Zero))
{
If ((Arg1 == One))
{
Return (Buffer (One)
{
0x03 // .
})
}
}
If ((Arg2 == One))
{
Return (Arg4)
}
}
Hence 1 or 3? Both return garbage. In fact I tried to brute-force the thing,
I never get anything relevant.
Here is the code:
#include <sys/ioctl.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dev/i2c/i2c_io.h>
struct i2c_hid_desc {
uint16_t wHIDDescLength;
uint16_t bcdVersion;
uint16_t wReportDescLength;
uint16_t wReportDescRegister;
uint16_t wInputRegister;
uint16_t wMaxInputLength;
uint16_t wOutputRegister;
uint16_t wMaxOutputLength;
uint16_t wCommandRegister;
uint16_t wDataRegister;
uint16_t wVendorID;
uint16_t wProductID;
uint16_t wVersionID;
uint32_t reserved;
} __packed;
int
main(void)
{
i2c_ioctl_exec_t iie;
u_int sc_hid_desc_addr = 0;
uint8_t get_desc_cmd[] = {
htole16(sc_hid_desc_addr) & 0xff,
htole16(sc_hid_desc_addr) >> 8,
};
struct i2c_hid_desc desc;
int fd;
if ((fd = open("/dev/iic2", O_RDWR)) == -1)
err(1, "open /dev/iic1 failed");
iie.iie_op = I2C_OP_READ_WITH_STOP;
iie.iie_addr = 0x5d;
iie.iie_cmd = get_desc_cmd;
iie.iie_cmdlen = sizeof(get_desc_cmd);
iie.iie_buf = (char *)&desc;
iie.iie_buflen = sizeof(desc);
if (ioctl(fd, I2C_IOCTL_EXEC, &iie) == -1)
return errno;
printf("bcdVersion = %04x\n", desc.bcdVersion);
return 0;
}
--
Emmanuel Dreyfus
manu%netbsd.org@localhost
Home |
Main Index |
Thread Index |
Old Index