Page MenuHomeFreeBSD

First draft HID over I2C support (Mouse only)
Needs ReviewPublic

Authored by marc.priggemeyer_gmail.com on Aug 12 2018, 10:51 PM.

Details

Reviewers
KOT_MATPOCKuH.Ru
Summary

Support for Human Interface Devices over I2C.

There are a couple of points to keep in mind:

Important notes:

  1. Currently iichid only supports mouse devices and therefore creates /dev/ims*.
  2. I use moused with settings in rc.conf like this: moused_port="/dev/ims0"
  3. I tried a few approaches to identify and attach an iichid device by querying ACPI directly from the iichid module. That failed on two details: parent association (in general HID over I2C devices appear below ACPI0 in NewBus but it is necessary to have them below the iicbus*/iic* nodes, moving these node in NewBus failed for me with a panic) and also interrupt handling (apparently, interrupts must be handled by the nodes the IRQs are assigned to (i.e. the node below ACPI0). Trying to attach to an IRQ from another node (i.e. a node below iicbus*/i2c*) fails)
  4. acpi_iichid creates a iichid node below the identifiable iicbus
  5. acpi_iichid enques a task either on interrupt or timeout and delegates retrieval of reports to iichid by callback
  6. iichid_load="YES" and acpi_iichid_load="YES" in loader.conf should work now without crash.

Stalled:

  1. Please refer to the changes I made to usbhid.h and usbhid.c, since I moved the generic hid functionality out of those files into two new ones. The long term aim would be to create a HID abstraction layer (called HID Caps) that will provide a general interface to HID capabilities and functions through the device tree. It will help to make it easier to use Human Interface Devices on different busses without the need of pulling USB into the kernel configuration. This is work in progress and, for now, independent of the I2C over HID support.
Test Plan

Load acpi_iichid and make sure to have an I2C controller driver (e.g. ig4) loaded beforehand. acpi_iichid should require iicbus and iichid as dependencies.

After loading you should see something like this (That is the output on my Dell Latitude 5480):
iichid_acpi0: <HID over I2C (ACPI)> irq 51 on acpi0
iichid_acpi0: descriptor register address is 20
iichid_acpi0: parent device is "\134_SB_.PCI0.I2C1"
iichid0: <HID over I2C> at addr 0x2c on iicbus1
iichid0: ADDR 0x2c REG 0x20
iichid0: 3 buttons and [XYZT] coordinates ID=1
iichid0: 3 buttons and [XYZT] coordinates ID=1
iichid0: determined (len=81) and described (len=83) input report lengths mismatch
iichid_acpi0: added iichid0 ADDR 0x2c REG 0x20 to iicbus1
iichid_acpi0: allocated irq at 0xfffff80004a46600 and rid 0
iichid_acpi0: successfully setup interrupt

vmstat -i should show statistics on interrupt handling.

Since interrupt resource acquisition is not always possible (in case of GPIO interrupts) acpi_iichid now supports a sampling_mode.
Set dev.acpi_iichid.#.sampling_rate to a value greater then 0 to activate sampling. A value of 0 is possible but will not reset the callout and, thereby, disable further report requests.
Do not set the sampling_rate value too high as it may result in periodical lags of cursor motion

  • e.g. 100 is the achievable rate in interrupt mode on my laptop, but is too high in sampling mode
  • rates between 30 and 60 samples per second appear to be a good tradeoff on my system.
  • 20 is too low on my machine

Another minor addition is a sysctl to invert the mouse wheel direction. Set dev.iichid.#.invert_scroll to test.

Diff Detail

Repository
rS FreeBSD src repository
Lint
Lint Skipped
Unit
Unit Tests Skipped

Event Timeline

marc.priggemeyer_gmail.com edited the test plan for this revision. (Show Details)Aug 12 2018, 11:36 PM

Daniel provideddmesg output for his laptop, thanks for the effort.
iichid_acpi0: <HID over I2C (ACPI)> on acpi0
iichid_acpi0: descriptor register address is 20
iichid_acpi0: unexpected type 17 while parsing Current Resource Settings (_CSR
)
iichid_acpi0: parent device is "\134_SB_.PCI0.I2C0"
iichid0: <HID over I2C> at addr 0x20 on iicbus0
iichid0: ADDR 0x20 REG 0x20
iichid0: determined (len=34) and described (len=36) input report lengths misma
tch
iichid_acpi0: added iichid0 ADDR 0x20 REG 0x20 to iicbus0
iichid_acpi0: allocated irq at 0x0 and rid 0
iichid_acpi0: could not allocate IRQ resource
iichid_acpi1: <HID over I2C (ACPI)> on acpi0
iichid_acpi1: descriptor register address is 20
iichid_acpi1: unexpected type 17 while parsing Current Resource Settings (_CSR
)
iichid_acpi1: parent device is "\134_SB_.PCI0.I2C1"
iichid1: <HID over I2C> at addr 0x15 on iicbus1
iichid1: ADDR 0x15 REG 0x20
iichid1: determined (len=62) and described (len=64) input report lengths misma
tch
iichid_acpi1: added iichid1 ADDR 0x15 REG 0x20 to iicbus1
iichid_acpi1: allocated irq at 0x0 and rid 0
iichid_acpi1: could not allocate IRQ resource

  1. input report length mismatch is exactly 2. The 2 byte length value was not considered so that message can be ignored. Will change the comparison accordingly. The I2C communication works and a HID descriptor is received. The problem is the IRQ, see below
  2. There is no IRQ assigned that the module could attach to. There should be a an ACPI IRQ resource type in the _CSR.
  3. _CSR parsing encounters type 17 ACPI resource. This is a bit of a problem because that indicates a GPIO and not an IRQ that could be directly attached to. I need to look into that. It might be necessary to modify ig4 if there is no possibilty to directly attach to a GPIO interrupt given an index.

Hi Marc,

This is my latest FreeBSD dmesg output:

iichid_acpi0: <HID over I2C (ACPI)> on acpi0
iichid_acpi0: descriptor register address is 20
iichid_acpi0: unexpected type 17 while parsing Current Resource Settings (_CSR)
iichid_acpi0: parent device is "\134_SB_.PCI0.I2C0"
iichid0: <HID over I2C> at addr 0x20 on iicbus0
iichid0: ADDR 0x20 REG 0x20
iichid0: determined (len=34) and described (len=36) input report lengths mismatch
iichid_acpi0: added iichid0 ADDR 0x20 REG 0x20 to iicbus0
iichid_acpi0: allocated irq at 0x0 and rid 0
iichid_acpi0: could not allocate IRQ resource
iichid_acpi1: <HID over I2C (ACPI)> on acpi0
iichid_acpi1: descriptor register address is 20
iichid_acpi1: unexpected type 17 while parsing Current Resource Settings (_CSR)
iichid_acpi1: parent device is "\134_SB_.PCI0.I2C1"
iichid1: <HID over I2C> at addr 0x15 on iicbus1
iichid1: ADDR 0x15 REG 0x20
iichid1: 2 buttons and [XY] coordinates ID=2
iichid1: 2 buttons and [XY] coordinates ID=2
iichid1: determined (len=62) and described (len=64) input report lengths mismatch
iichid_acpi1: added iichid1 ADDR 0x15 REG 0x20 to iicbus1
iichid_acpi1: allocated irq at 0x0 and rid 0
iichid_acpi1: could not allocate IRQ resource


I also collected some information regarding the Touchscreen and Touchpad based on what Ubuntu finds.


iichid0: <HID over I2C> at addr 0x20 on iicbus0
-> This is the Touchscreen ( SYNA2393:00 06CB:19AC )

iichid1: <HID over I2C> at addr 0x15 on iicbus1
-> This is the Touchpad ( SYNA1D31:00 06CB:CD48 Touchpad )


➜ ~ sudo cat /proc/interrupts

          CPU0       CPU1       CPU2       CPU3       CPU4       CPU5       CPU6       CPU7        
16:          0          0          0          0        840          0          0          0  IR-IO-APIC   16-fasteoi   idma64.0, i2c_designware.0
17:          0          0          0          0          0          0      16748          0  IR-IO-APIC   17-fasteoi   idma64.1, i2c_designware.1

136: 0 0 2 0 0 0 0 0 intel-gpio 145 SYNA2393:00
138: 0 0 246 0 0 0 0 0 intel-gpio 85 SYNA1D31:00


➜ ~ sudo i2cdetect -l
i2c-3 i2c DPDDC-A I2C adapter
i2c-13 i2c nvkm-0000:01:00.0-aux-0005 I2C adapter
i2c-1 i2c i915 gmbus dpb I2C adapter
i2c-11 i2c nvkm-0000:01:00.0-aux-0004 I2C adapter
i2c-8 i2c nvkm-0000:01:00.0-bus-0001 I2C adapter
i2c-6 i2c Synopsys DesignWare I2C adapter I2C adapter
i2c-4 i2c DPDDC-B I2C adapter
i2c-2 i2c i915 gmbus dpd I2C adapter
i2c-12 i2c nvkm-0000:01:00.0-bus-0005 I2C adapter
i2c-0 i2c i915 gmbus dpc I2C adapter
i2c-9 i2c nvkm-0000:01:00.0-bus-0002 I2C adapter
i2c-10 i2c nvkm-0000:01:00.0-bus-0004 I2C adapter
i2c-7 i2c Synopsys DesignWare I2C adapter I2C adapter
i2c-5 i2c DPDDC-C I2C adapter


➜ ~ sudo lspci -v
00:15.0 Signal processing controller: Intel Corporation Sunrise Point-LP Serial IO I2C Controller #0 (rev 21)
Subsystem: Huawei Technologies Co., Ltd. Sunrise Point-LP Serial IO I2C Controller
Flags: bus master, fast devsel, latency 0, IRQ 16
Memory at 2ff3021000 (64-bit, non-prefetchable) [size=4K]
Capabilities: [80] Power Management version 3
Capabilities: [90] Vendor Specific Information: Len=14 <?>
Kernel driver in use: intel-lpss
Kernel modules: intel_lpss_pci

00:15.1 Signal processing controller: Intel Corporation Sunrise Point-LP Serial IO I2C Controller #1 (rev 21)
Subsystem: Huawei Technologies Co., Ltd. Sunrise Point-LP Serial IO I2C Controller
Flags: bus master, fast devsel, latency 0, IRQ 17
Memory at 2ff3020000 (64-bit, non-prefetchable) [size=4K]
Capabilities: [80] Power Management version 3
Capabilities: [90] Vendor Specific Information: Len=14 <?>
Kernel driver in use: intel-lpss
Kernel modules: intel_lpss_pci


➜ ~ sudo i2cdetect -r 6
[sudo] password for jackd:
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-6 using receive byte commands.
I will probe address range 0x03-0x77.
Continue? [Y/n] y

0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f

00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
➜ ~ sudo i2cdetect -r 7
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-7 using receive byte commands.
I will probe address range 0x03-0x77.
Continue? [Y/n] y

0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f

00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- UU -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --


➜ ~ xinput
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ Logitech G300s Optical Gaming Mouse id=10 [slave pointer (2)]
⎜ ↳ SYNA2393:00 06CB:19AC id=13 [slave pointer (2)]
⎜ ↳ SYNA1D31:00 06CB:CD48 Touchpad id=14 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]

↳ Virtual core XTEST keyboard             	id=5	[slave  keyboard (3)]
↳ Power Button                            	id=6	[slave  keyboard (3)]
↳ Video Bus                               	id=7	[slave  keyboard (3)]
↳ Video Bus                               	id=8	[slave  keyboard (3)]
↳ Power Button                            	id=9	[slave  keyboard (3)]
↳ Logitech G300s Optical Gaming Mouse     	id=11	[slave  keyboard (3)]
↳ HD Camera: HD Camera                    	id=12	[slave  keyboard (3)]
↳ AT Translated Set 2 keyboard            	id=15	[slave  keyboard (3)]

➜ ~ xinput list --long

⎜ ↳ SYNA2393:00 06CB:19AC id=13 [slave pointer (2)]
Reporting 6 classes:

		Class originated from: 13. Type: XIButtonClass
		Buttons supported: 7
		Button labels: "Button Left" "Button Middle" "Button Right" "Button Wheel Up" "Button Wheel Down" "Button Horiz Wheel Left" "Button Horiz Wheel Right"
		Button state:
		Class originated from: 13. Type: XIValuatorClass
		Detail for Valuator 0:
		  Label: Abs MT Position X
		  Range: 0.000000 - 65535.000000
		  Resolution: 0 units/m
		  Mode: absolute
		  Current value: 34503.000000
		Class originated from: 13. Type: XIValuatorClass
		Detail for Valuator 1:
		  Label: Abs MT Position Y
		  Range: 0.000000 - 65535.000000
		  Resolution: 0 units/m
		  Mode: absolute
		  Current value: 8089.000000
		Class originated from: 13. Type: XIValuatorClass
		Detail for Valuator 2:
		  Label: Rel Horiz Scroll
		  Range: -1.000000 - -1.000000
		  Resolution: 0 units/m
		  Mode: relative
		Class originated from: 13. Type: XIValuatorClass
		Detail for Valuator 3:
		  Label: Rel Vert Scroll
		  Range: -1.000000 - -1.000000
		  Resolution: 0 units/m
		  Mode: relative
		Class originated from: 13. Type: XITouchClass
		Touch mode: direct
		Max number of touches: 15

⎜ ↳ SYNA1D31:00 06CB:CD48 Touchpad id=14 [slave pointer (2)]
Reporting 7 classes:

		Class originated from: 14. Type: XIButtonClass
		Buttons supported: 12
		Button labels: "Button Left" "Button Middle" "Button Right" "Button Wheel Up" "Button Wheel Down" "Button Horiz Wheel Left" "Button Horiz Wheel Right" None None None None None
		Button state:
		Class originated from: 14. Type: XIValuatorClass
		Detail for Valuator 0:
		  Label: Rel X
		  Range: 0.000000 - 1397.000000
		  Resolution: 12000 units/m
		  Mode: relative
		Class originated from: 14. Type: XIValuatorClass
		Detail for Valuator 1:
		  Label: Rel Y
		  Range: 0.000000 - 888.000000
		  Resolution: 12000 units/m
		  Mode: relative
		Class originated from: 14. Type: XIValuatorClass
		Detail for Valuator 2:
		  Label: Rel Horiz Scroll
		  Range: 0.000000 - -1.000000
		  Resolution: 0 units/m
		  Mode: relative
		Class originated from: 14. Type: XIValuatorClass
		Detail for Valuator 3:
		  Label: Rel Vert Scroll
		  Range: 0.000000 - -1.000000
		  Resolution: 0 units/m
		  Mode: relative
		Class originated from: 14. Type: XIScrollClass
		Scroll info for Valuator 2
		  type: 2 (horizontal)
		  increment: 33.000000
		  flags: 0x0
		Class originated from: 14. Type: XIScrollClass
		Scroll info for Valuator 3
		  type: 1 (vertical)
		  increment: -33.000000
		  flags: 0x0

Hi Daniel,

apparently, your touchpad is recognized as mouse device and could be used.

There are only mouse devices supported yet as iichid mimics ums behaviour (refer to the adapted hid parsing code sections). Thus, your touchscreen won't work for now.

The problem remains with the interrupt handling. CSR contains a reference to a GPIO line that is used to signal new data. That is also confirmed by your Linux tests. It says "intel gpio" as interrupt source for your touchpad and touchscreen. I cannot say if how far GPIO support has progressed so far, but I assume that there will be some more work involved to get that working.

Next step for me will be the following:
Add sysctl switches for these type of devices to toggle interrupt and polling mode. That will hopefully get your touchpad working at the least. Also I will integrate some switches to dump the descriptors.
You can continue testing then and verify that your devices are recognized correctly. And I will add the HID layer and remove the mouse specific stuff from iichid.
GPIO support will follow afterwards as time permits.

I really appreciate all the hard work you have already putted into that and the commitment you show.
Looking forward to support with testing.

Do you know the people who might be working on "I cannot say if how far GPIO support has progressed so far, but I assume that there will be some more work involved to get that working." or can you point me to the area of code which might be relevant for this ?

It appears that GPIO interrupt allocation is implemented in general, but I think chipset support might yet be missing for Intel PCH.

For documentation purposes, following this commit there was a chain of changes to gpiobus (sys/dev/gpio): https://github.com/freebsd/freebsd/commit/1e1149563f886677c0347755d702a76c759ff77e

marc.priggemeyer_gmail.com edited the summary of this revision. (Show Details)
marc.priggemeyer_gmail.com edited the test plan for this revision. (Show Details)
  • Tested against base revision 338291.
  • Sampling mode was added to periodically poll for reporrts (see Test Plan for further information)
  • Still make sure to have a running iicbus implementation
  • it was reported in https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=221777 that a panic occures when trying to load iichid and acpi_iichid by bootloader kld_list in rc.conf is still the way to go if you tested manually beforehand.
marc.priggemeyer_gmail.com edited the test plan for this revision. (Show Details)Sep 22 2018, 9:31 PM

Hello,

First thanks for your work. I've got a Dell Latitude 5590. Scanning I2C bus now work.
root@pcb-prdtfa-07:~ # i2c -f /dev/iic1 -s
Hardware may not support START/STOP scanning; trying less-reliable read method.
Scanning I2C devices on /dev/iic1: 2c

I've properly patch source, but I kernel compilation does not end properly.

cc -c -O2 -pipe -fno-strict-aliasing -g -nostdinc -I. -I../../.. -I../../../contrib/libfdt -D_KERNEL -DHAVE_KERNEL_OPTION_HEADERS -include opt_global.h -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -MD -MF.depend.hid.o -MThid.o -mcmodel=kernel -mno-red-zone -mno-mmx -mno-sse -msoft-float -fno-asynchronous-unwind-tables -ffreestanding -fwrapv -fstack-protector -gdwarf-2 -Wall -Wredundant-decls -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Winline -Wcast-qual -Wundef -Wno-pointer-sign -Dprintf=freebsd_kprintf -Wmissing-include-dirs -fdiagnostics-show-option -Wno-unknown-pragmas -Wno-error-tautological-compare -Wno-error-empty-body -Wno-error-parentheses-equality -Wno-error-unused-function -Wno-error-pointer-sign -Wno-error-shift-negative-value -Wno-error-address-of-packed-member -mno-aes -mno-avx -std=iso9899:1999 -Werror ../../../dev/usb/hid.c
../../../dev/usb/hid.c:363:19: error: implicit conversion from 'int' to 'uint8_t' (aka 'unsigned char') changes value from 1024

to 0 [-Werror,-Wconstant-conversion]
                                          s->ncount = MAXLOCCNT;
                                                    ~ ^~~~~~~~~

../../../dev/usb/hid.c:78:19: note: expanded from macro 'MAXLOCCNT'
#define MAXLOCCNT 1024

^~~~

../../../dev/usb/hid.c:803:7: error: use of undeclared identifier 'HUM_CENTIMETER'

case HUM_CENTIMETER:
     ^

../../../dev/usb/hid.c:807:7: error: use of undeclared identifier 'HUM_INCH'

case HUM_INCH:
     ^

../../../dev/usb/hid.c:811:7: error: use of undeclared identifier 'HUM_RADIAN'

case HUM_RADIAN:
     ^

../../../dev/usb/hid.c:815:7: error: use of undeclared identifier 'HUM_DEGREE'

case HUM_DEGREE:
     ^

5 errors generated.

  • Error code 1

Stop.
make: stopped in /usr/src/sys/amd64/compile/GENERIC

Could you advise ?

Thanks

Thomas

Hi Thomas,

Thanks for testing. What's your source revision?

At this point, it appears to me that it wasn't such a good idea to include changes to usb. I will prepare a new patch against a more recent source revision and remove these (for now unecessary) changes. That will make iichid more self contained and easier to validate.

Best regards,
Marc

Hello Marc,

Thanks for your quick answer.

My revision is r339210. So I guess I should try 338291.

Regards

Thomas

Hello Marc,

Thanks for your quick answer.

My revision is r339210. So I guess I should try 338291.

Regards

Thomas

Hi Thomas,

I would suggest you stick to the source revision you already have (running or intending to run) and makeworld/makekernel without patch. Afterwards patch and go to sys/modules/i2c/iichid and sys/modules/acpi/acpi_iichid and run make only for these two modules. That would also be the quickest test if you already have a running system. *.ko files will then be below /usr/obj.

My changes to usb_hid.c/.h appear to break a few things, so I see a big chance for 338291 to also error out on the same modules.

Best regards,
Marc

driver bug: Unable to set devclass (class: ppc devname: (unknown))
driver bug: Unable to set devclass (class: ppc devname: (unknown))
ig4iic_acpi0: <Designware I2C Controller> iomem 0xe1122000-0xe1122fff irq 7 on acpi0
ig4iic_acpi0: controller error during attach-1
driver bug: Unable to set devclass (class: ppc devname: (unknown))
ig4iic_acpi1: <Designware I2C Controller> iomem 0xe1124000-0xe1124fff irq 7 on acpi0
ig4iic_acpi1: controller error during attach-1
iicbus0: <Philips I2C bus> on ig4iic_acpi0
iic0: <I2C generic I/O> on iicbus0
iicbus1: <Philips I2C bus> on ig4iic_acpi1
iic1: <I2C generic I/O> on iicbus1
driver bug: Unable to set devclass (class: ppc devname: (unknown))
wlan0: Ethernet address: 6c:29:95:4e:a3:68

Looks like acpi_iichid isn't attaching to anything acpi..hmmmm.

Id Refs Address Size Name
1 107 0xffffffff80200000 24528e0 kernel
2 1 0xffffffff82653000 940c8 linux64.ko
3 5 0xffffffff826e8000 8a10 linux_common.ko
4 1 0xffffffff826f1000 2be8 coretemp.ko
5 1 0xffffffff826f4000 1011a8 iwm7260fw.ko
6 1 0xffffffff827f6000 a6780 linux.ko
7 1 0xffffffff8289d000 10be0 tmpfs.ko
8 1 0xffffffff828ae000 3a86f0 zfs.ko
9 2 0xffffffff82c57000 a4f0 opensolaris.ko
10 1 0xffffffff82c63000 166f8 fuse.ko
11 1 0xffffffff82c7a000 2a138 if_iwm.ko
12 1 0xffffffff835fa000 19e0 fdescfs.ko
13 1 0xffffffff835fc000 490c linprocfs.ko
14 1 0xffffffff83601000 194c linsysfs.ko
15 1 0xffffffff83603000 120040 i915kms.ko
16 1 0xffffffff83724000 74810 drm.ko
17 4 0xffffffff83799000 104b0 linuxkpi.ko
18 3 0xffffffff837aa000 11300 linuxkpi_gplv2.ko
19 2 0xffffffff837bc000 6c0 debugfs.ko
20 1 0xffffffff837bd000 f98 iic.ko
21 5 0xffffffff837be000 2020 iicbus.ko
22 1 0xffffffff837c1000 35e8 ig4.ko
25 1 0xffffffff837c9000 3aa0 ng_ubt.ko
26 5 0xffffffff837cd000 a020 netgraph.ko
27 1 0xffffffff837d8000 9608 ng_hci.ko
28 3 0xffffffff837e2000 9c0 ng_bluetooth.ko
29 1 0xffffffff837e3000 cd40 ng_l2cap.ko
30 1 0xffffffff837f0000 1b9c0 ng_btsocket.ko
31 1 0xffffffff8380c000 2190 ng_socket.ko
32 1 0xffffffff8380f000 acf mac_ntpd.ko
33 1 0xffffffff83810000 2120 acpi_wmi.ko
34 1 0xffffffff83813000 2b98 acpi_video.ko
35 1 0xffffffff837c5000 1470 acpi_iichid.ko
36 1 0xffffffff837c7000 1d30 iichid.ko

Let's see what a debug boot shows...this box is strange and running an odd coreboot.

Table 'FACP' at 0x78f10960
FACP: Found table at 0x78f10960
ppc: ppc-1 already exists; skipping it
driver bug: Unable to set devclass (class: ppc devname: (unknown))
Table 'FACP' at 0x78f10960
FACP: Found table at 0x78f10960
Table 'FACP' at 0x78f10960
FACP: Found table at 0x78f10960
Table 'FACP' at 0x78f10960
FACP: Found table at 0x78f10960
Table 'FACP' at 0x78f10960
FACP: Found table at 0x78f10960
Table 'FACP' at 0x78f10960
FACP: Found table at 0x78f10960
Table 'FACP' at 0x78f10960
FACP: Found table at 0x78f10960
Table 'FACP' at 0x78f10960
FACP: Found table at 0x78f10960
Table 'FACP' at 0x78f10960
FACP: Found table at 0x78f10960
Table 'FACP' at 0x78f10960
FACP: Found table at 0x78f10960
Table 'FACP' at 0x78f10960
FACP: Found table at 0x78f10960
Table 'FACP' at 0x78f10960
FACP: Found table at 0x78f10960

Hmmm. Does my ACPI table not _know_ there should be an i2c mouse?

KOT_MATPOCKuH.Ru accepted this revision.Oct 10 2018, 8:34 PM
KOT_MATPOCKuH.Ru added a subscriber: KOT_MATPOCKuH.Ru.

I'm applied this patch to my FreeBSD 12 r338342 box on Dell Latitude 5290 and applied this configuration to rc.conf:
kld_list="/boot/modules/i915kms.ko /boot/modules/iichid.ko /boot/modules/acpi_iichid.ko"
moused_port="/dev/ims0"

Also I changed device for mouse driver in xorg.conf:
Option "Device" "/dev/ims0"

I'm got this messages in /var/run/dmesg.boot:
iichid_acpi0: <HID over I2C (ACPI)> irq 51 on acpi0
iichid_acpi0: descriptor register address is 20
iichid_acpi0: parent device is "\134_SB_.PCI0.I2C1"
iichid0: <HID over I2C> at addr 0x2c on iicbus1
iichid0: ADDR 0x2c REG 0x20
iichid0: 3 buttons and [XYZT] coordinates ID=1
iichid0: 3 buttons and [XYZT] coordinates ID=1
iichid0: determined (len=28) and described (len=30) input report lengths mismatch
iichid_acpi0: added iichid0 ADDR 0x2c REG 0x20 to iicbus1
iichid_acpi0: allocated irq at 0xfffff8001ee9d300 and rid 0
iichid_acpi0: successfully setup interrupt

And got working touchpad in console and X.

Some problems:

  1. Without started moused X.org hangs on start
  2. Kernel panic occurs after enabling to load this modules on boot time from loader.conf
This revision is now accepted and ready to land.Oct 10 2018, 8:34 PM

Hmmm. Does my ACPI table not _know_ there should be an i2c mouse?

ig4 does not attach on your system, even though the iicbus and iic devices are created (which is weird imo). So you could try enumerating devices on iic0 or iic1, but I believe you won't have any successful communication on the I2C bus. You could try the following tool (don't remember where it's from, not mine though). Compile and run with full path of iic# device as first argument (enumerates devices on an I2C bus):

#include <sys/cdefs.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <unistd.h>
#include <dev/iicbus/iic.h>

int main(int argc, char** argv)
{
	int i ,fd;

	if (argc < 2)
	{
		perror("usage: ./a.out device");
		return -1;
	}

	const char* dev = argv[1];
	uint8_t buf[2] = {0, 0};
	struct iic_msg msg[2];
	struct iic_rdwr_data rdwr;

	msg[0].flags = !IIC_M_RD;
	msg[0].len = sizeof(buf);
	msg[0].buf = buf;

	msg[1].flags = IIC_M_RD;
	msg[1].len = sizeof(buf);
	msg[1].buf = buf;

	rdwr.nmsgs = 2;

	if( (fd = open(dev, O_RDWR)) < 0 ) {
		perror("open");
		exit(-1);
	}

	setbuf(stdout, 0);
	for(i=1; i<128; i++) {
		msg[0].slave = i;
		msg[1].slave = i;
		rdwr.msgs = msg;

		if( ioctl(fd, I2CRDWR, &rdwr) >= 0 )
			printf(" 0x%02x ", i);
		else
			printf(".");
	}
	printf("\n");
	close(fd);
	exit(0);
}

Besides that, I think you really will have to fix your ig4 problem first (https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=221777). By the way, the ACPI information you provided there suggests that the HID device is a trackpad. That is not supported yet, since iichid only searches for mouse information in the descriptor.

Besides that, I think you really will have to fix your ig4 problem first (https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=221777). By the way, the ACPI information you provided there suggests that the HID device is a trackpad. That is not supported yet, since iichid only searches for mouse information in the descriptor.

Considering the firmware is slightly-custom, that might just be a human-readable reference. I am not entirely sure.

I just uploaded a new diff that lacks the changes to usb. iichid for now depends on usb but should be easier to test.

This revision now requires review to proceed.Oct 12 2018, 8:02 PM

I got some open questions that someone actually reviewing this code or just stumbling by might be able to answer:

  1. is PI_TTY the preferred thread priority, or should it be something else?
  2. I read locking(9), mutex(9), bus_setup_intr(9) and a paper on locking mechanisms in FreeBSD and think that I got a fair idea about the basic principles, but I think I still didn't get a grasp on when sleeping is allowed when using an interrupt routine. From what I understand, I almost always need to create a task queue due to the fact that almost all bus implementations call mtx_sleep at some point. Is that correct? Then again I think I saw some modules calling bus operations (that possibly call mtx_sleep) during interrupt handling directly from the associated ithread routine. Are they doing it wrong?
  3. If I use a task queue to handle interrupts and retrieve data from a device and that retrieval method goes to sleep eventually. From my understanding I should release my locks before and reacquire them after the bus operation. What is the preferred method to prevent another thread trying to detach the sleeping module? Possible solutions I figured that might be applicable are flag and condition variable or nested mutex. But what is the right way to do it, or is it even unnecessary because some internal mechanism prevents detaching (device busy msg)?

Thanks for your help.

Best,
Marc

markj added a subscriber: markj.Oct 13 2018, 10:17 PM

I was able to use this on a Dell latitude 7480 to get a working trackpad. Thank you!

I haven't spent any significant amount of time looking at the diff yet, but I'll take a stab at answering these.

I got some open questions that someone actually reviewing this code or just stumbling by might be able to answer:

  1. is PI_TTY the preferred thread priority, or should it be something else?

I don't yet understand the code well enough to say. PI_TTY is for the TTY subsystem and thus probably doesn't quite make sense here. PI_DULL strikes me as a reasonable priority to use here.

  1. I read locking(9), mutex(9), bus_setup_intr(9) and a paper on locking mechanisms in FreeBSD and think that I got a fair idea about the basic principles, but I think I still didn't get a grasp on when sleeping is allowed when using an interrupt routine. From what I understand, I almost always need to create a task queue due to the fact that almost all bus implementations call mtx_sleep at some point. Is that correct? Then again I think I saw some modules calling bus operations (that possibly call mtx_sleep) during interrupt handling directly from the associated ithread routine. Are they doing it wrong?

It's never correct to sleep (e.g., by calling mtx_sleep()) in an ithread context. Could you point out the code you're referring to? In general it seems quite odd to me to call sleepable bus methods from an ithread handler.

  1. If I use a task queue to handle interrupts and retrieve data from a device and that retrieval method goes to sleep eventually. From my understanding I should release my locks before and reacquire them after the bus operation. What is the preferred method to prevent another thread trying to detach the sleeping module? Possible solutions I figured that might be applicable are flag and condition variable or nested mutex. But what is the right way to do it, or is it even unnecessary because some internal mechanism prevents detaching (device busy msg)?

Driver detach code should ensure that all taskqueues associated with the driver are stopped by calling taskqueue_drain(). This function may sleep while waiting for a taskqueue handler to complete. See the taskqueue(9) man page for more details.

There are indeed mechanisms which can block unload of a busy module, e.g., by calling device_busy() when a device file is opened.

sys/dev/iicbus/input/acpi_iichid.c
1

This file is missing a license header.

sys/dev/iicbus/input/iichid.c
1

This file is missing a license header.

sys/modules/acpi/acpi_iichid/Makefile
4

Don't forget to add this to the Makefile in the parent acpi/ directory.

First, good job!

I have an Acer Aspire E 11 (E3-112-P579).
In the BIOS I can set the touchpad to either "Basic" or "Advanced", meaning it functions as a PS/2 or I2C device.
I belive it is a Synaptics device, since with the sysctl hw.psm.synaptics_support=1 two finger scrolling works.
(And hardware ID seems to be "SYN1B7D")

I set the BIOS to "Advanced" and tested this patch. It attaches;

kernel: acpi_iichid0: <HID over I2C (ACPI)> irq 67 on acpi
0
kernel: acpi_iichid0: descriptor register address is 20
kernel: acpi_iichid0: - irq: 67
kernel: acpi_iichid0: parent device is "\_SB_.I2C1"
kernel: iichid0: <HID over I2C> at addr 0x2c on iicbus0
kernel: iichid0: ADDR 0x2c REG 0x20
kernel: iichid0: 2 buttons and [XY] coordinates ID=2
syslogd: last message repeated 1 times
kernel: acpi_iichid0: added iichid0 ADDR 0x2c REG 0x20 to iicbus0
kernel: acpi_iichid0: allocated irq at 0xfffff8000a2f7400 and rid 0
kernel: acpi_iichid0: successfully setup interrupt
kernel: iichid0: no data received
syslogd: last message repeated 1 times
kernel: iichid0: no blocks available
syslogd: last message repeated 61 times
syslogd: last message repeated 12 times

It works, but there is only one button and no two finger scrolling, whereas with psm I have 3 buttons (one, two and three finger taps) and two finger scrolling.

...
I haven't spent any significant amount of time looking at the diff yet, but I'll take a stab at answering these.
...

Your answers were very helpful, thanks alot. I can build upon that and fix some obvious errors I made in my implementation.

...

I set the BIOS to "Advanced" and tested this patch. It attaches;

...
kernel: iichid0: 2 buttons and [XY] coordinates ID=2
...

It works, but there is only one button and no two finger scrolling, whereas with psm I have 3 buttons (one, two and three finger taps) and two finger scrolling.

Thanks for testing. That your two finger scroll does not work is apparent from the descriptor line identifying only two axis, namely X and Y. For scrolling to work, there should be a Z axis as well. I believe that your touchpad does not only support the mouse reports but also multitouch trackpad reports, but they are not yet considered by iichid. Nevertheless you should be able to use two buttons.

It works, but there is only one button and no two finger scrolling, whereas with psm I have 3 buttons (one, two and three finger taps) and two finger scrolling.

Thanks for testing. That your two finger scroll does not work is apparent from the descriptor line identifying only two axis, namely X and Y. For scrolling to work, there should be a Z axis as well. I believe that your touchpad does not only support the mouse reports but also multitouch trackpad reports, but they are not yet considered by iichid. Nevertheless you should be able to use two buttons.

I did some more testing. I can only get button 1 events, by tapping with one finger. This is one of those I think are called clickpad, pushing down on the pad it clicks a physical button. That does not generate an event. However, it doesn't generate a button event in PS/2 mode either.

@marc.priggemeyer_gmail.com hello sir can you be so kind to help me out, when I try to kldload acpi_iichid.ko it says 'parent is not attached', what should I kldload beforehand or something should be done?

@marc.priggemeyer_gmail.com
sorry for bothering you guys
I have managed to kldload acpi_iicbus.ko
but my mosuepad doesn't work
here is my latest FreeBSD dmesg output:
ig4iic_pci0: <Intel Sunrise Point-LP I2C Controller-0> mem 0xd2336000-0xd2336fff at device 21.0 on pci0
ig4iic_pci0: Using MSI
iicbus0: <Philips I2C bus> on ig4iic_pci0
acpi_iichid0: <HID over I2C (ACPI)> irq 51 on acpi0
acpi_iichid0: descriptor register address is 1
acpi_iichid0: - irq: 51
acpi_iichid0: parent device is "\134_SB_.PCI0.I2C0"
iichid0: <HID over I2C> at addr 0x15 on iicbus0
iichid0: ADDR 0x15 REG 0x1
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(672) truncated to 255
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(672) truncated to 255
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(672) truncated to 255
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(672) truncated to 255
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(672) truncated to 255
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(672) truncated to 255
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(672) truncated to 255
iichid0: 3 buttons and [XY] coordinates ID=1
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(672) truncated to 255
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(672) truncated to 255
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(672) truncated to 255
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(672) truncated to 255
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(672) truncated to 255
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(672) truncated to 255
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(672) truncated to 255
iichid0: 3 buttons and [XY] coordinates ID=1
hid_get_item: Number of items(256) truncated to 255
hid_get_item: Number of items(672) truncated to 255
acpi_iichid0: added iichid0 ADDR 0x15 REG 0x1 to iicbus0
acpi_iichid0: allocated irq at 0xfffff801088b6780 and rid 0
acpi_iichid0: successfully setup interrupt

besides that function iichid_event in iichid.c keep printing "no data received\n"
can you be so kind to take a sight

Awesome Mark.
It works on my Huawei Matebook X Pro. Sorry for comming back so late.
I had 10 minutes to test and here are my initial findings.

Notes:

  • tested on FreeBSD ALPHA-10
  • loaded ig4 from /boot/loader.conf
  • loading iichid and acpi_iichid from /boot/loader.conf leads to panic. Adding it to /etc/rc.conf works
  • moused_port="/dev/ims1" set in /etc/rc.conf
  • moused_enable="YES" set in /etc/rc.conf
  • /usr/local/etc/X11/xorg.conf.d/mouse.conf created and ' Option "Device" "/dev/ims1" ' added
  • in /etc/sysctl.conf -> dev.acpi_iichid.1.sampling_rate=20
  • Moving the cursor works. Once its moving, it will only stop when I tap the touchpad.
  • holding the touchpad down with one finger and moving a second finger to select text works
  • Suspend/Resume does not work. However this is still an issue with ig4 I guess.

Thanks for doing this! Works great on my Dell 7490.
Suspend/resume not tested. Please also add EVDEV to this driver so we can get things like horizontal scrolling :)

/etc/rc.conf

kld_list="ig4 acpi_iichid"
moused_port="/dev/ims0"
moused_enable="YES"

/etc/X11/xorg.d/mouse.conf

Section "InputClass"
	Identifier "Touchpad"
	Option "Device" "/dev/ims0"
EndSection

Many thanks for these files and patches.
Now my Asus Vivobook S15 touchpad is working running FreeBSD 12.RC1, kernel source revision 340904.

Norice that setting iichid_load="YES" and acpi_iichid_load="YES" in either /boot/loader.conf or /etc/rc.conf lead to crash, have to be set in /etc/rc.conf kld_list variable.

dmesg

[ ... ]
iicbus0: <Philips I2C bus> on ig4iic_pci0
iicbus1: <Philips I2C bus> on ig4iic_pci1
iic0: <I2C generic I/O> on iicbus0
iic1: <I2C generic I/O> on iicbus1
iicsmb0: <SMBus over I2C bridge> on iicbus0
iicsmb1: <SMBus over I2C bridge> on iicbus1
smbus0: <System Management Bus> on iicsmb0
smbus1: <System Management Bus> on iicsmb1
acpi_iichid0: <HID over I2C (ACPI)> irq 109 on acpi0
acpi_iichid0: descriptor register address is 1
acpi_iichid0: - irq: 109
acpi_iichid0: parent device is "\134_SB_.PCI0.I2C1"
iichid0: <HID over I2C> at addr 0x15 on iicbus1
iichid0: ADDR 0x15 REG 0x1
iichid0: 2 buttons and [XYZT] coordinates ID=1
iichid0: 2 buttons and [XYZT] coordinates ID=1
acpi_iichid0: added iichid0 ADDR 0x15 REG 0x1 to iicbus1
acpi_iichid0: allocated irq at 0xfffff80009ea2a80 and rid 0
acpi_iichid0: successfully setup interrupt
iichid0: could not retrieve input report (3)
iichid0: an error occured
iichid0: could not retrieve input report (3)
iichid0: an error occured

arrowd added a subscriber: arrowd.Dec 10 2018, 2:09 PM

Builds on 12.0-STABLE r343501 sources and works fine with Dell Latitude 5590. Thank you!

kwm added a subscriber: kwm.Feb 3 2019, 11:24 AM
Scoobi_doo_yahoo.com added a comment.EditedFeb 15 2019, 7:01 PM

I'm working on adding support for the Intel DesignWare I2C controllers that are connected to my touchpad and my touchscreen, also to the touchpad of another user (who originally requested my help on this issue for his laptop). I think I have a working I2C device(running 'i2c -s -v -f /dev/iic0' kills my working PS/2-connected touchpad). I would like to use your iichid module to instantly add support for these HID devices, but when I build & load iichid I see no new HID device nodes.

What is the general procedure (using iichid) for adding a given I2C HID device that resides on a particular I2C bus attached to a particular I2C controller? I don't think my ACPI tables define the I2C addresses or control registers of the HID devices.

Thanks,
Anthony Jenkins

justus_sutsuj.com added a comment.EditedSun, Mar 31, 12:32 AM

Thank you very much Marc. I have been waiting for this and really appreciate your work.

It works almost for me on an ASUS UX310. Sometimes after boot I need to load the iic kernel module and scan the bus using i2c -s -f /dev/iic1.
Furthermore two finger scrolling does not work but it seems to be recognized. At least the cursor does not move during scrolling. The middle mouse button does not work as well.

Here is my dmesg output:

Mar 30 23:59:49 maerz kernel: ig4iic_pci0: <Intel Sunrise Point-LP I2C Controller-0> mem 0xef137000-0xef137fff at device 21.0 on pci0
Mar 30 23:59:49 maerz kernel: ig4iic_pci0: Using MSI
Mar 30 23:59:49 maerz kernel: iicbus0: <Philips I2C bus> on ig4iic_pci0
Mar 30 23:59:49 maerz kernel: ig4iic_pci1: <Intel Sunrise Point-LP I2C Controller-1> mem 0xef136000-0xef136fff at device 21.1 on pci0
Mar 30 23:59:49 maerz kernel: ig4iic_pci1: Using MSI
Mar 30 23:59:49 maerz kernel: iicbus1: <Philips I2C bus> on ig4iic_pci1
Mar 30 23:59:49 maerz kernel: acpi_iichid0: <HID over I2C (ACPI)> irq 109 on acpi0
Mar 30 23:59:49 maerz kernel: acpi_iichid0: descriptor register address is 1
Mar 30 23:59:49 maerz kernel: acpi_iichid0:  - irq: 109
Mar 30 23:59:49 maerz kernel: acpi_iichid0: parent device is "\_SB_.PCI0.I2C1"
Mar 30 23:59:49 maerz kernel: iichid0: <HID over I2C> at addr 0x15 on iicbus1
Mar 30 23:59:49 maerz kernel: iichid0: ADDR 0x15 REG 0x1
Mar 30 23:59:49 maerz kernel: iichid0: 2 buttons and [XYZT] coordinates ID=1
Mar 30 23:59:49 maerz syslogd: last message repeated 1 times
Mar 30 23:59:49 maerz kernel: acpi_iichid0: added iichid0 ADDR 0x15 REG 0x1 to iicbus1
Mar 30 23:59:49 maerz kernel: acpi_iichid0: allocated irq at 0xfffff8002b1dab00 and rid 0
Mar 30 23:59:49 maerz kernel: acpi_iichid0: successfully setup interrupt
Mar 30 23:59:58 maerz kernel: iichid0: no data received
Mar 31 00:00:00 maerz syslogd: last message repeated 271 times
Mar 31 00:00:00 maerz kernel: iichid0: no data received
Mar 31 00:00:13 maerz syslogd: last message repeated 607 times
Mar 31 00:00:38 maerz kernel: iic0: <I2C generic I/O> on iicbus0
Mar 31 00:00:38 maerz kernel: iic1: <I2C generic I/O> on iicbus1
Mar 31 00:00:39 maerz kernel: iichid0: no data received
Mar 31 00:00:52 maerz syslogd: last message repeated 477 times
Mar 31 00:00:59 maerz kernel: iichid0: no data received
Mar 31 00:01:09 maerz syslogd: last message repeated 124 times

Justus