# HID over I2C Touchpad support ? - Huawei Matebook X Pro



## pbp_jackd (Jul 6, 2018)

I recently bought a Huawei Matebook X Pro. Out of the box 11.2 and 12-Current boot. 
However, the touchpad and touchscreen are not even being detected at all.
I tested Ubuntu 18.04 on it as well, which detects all hardware just fine. It turns out the laptop has a Synaptic touchpad connected over I2C.

Is anyone aware if HID over I2C will come to FreeBSD any time soon ?

Yesterday I tested to add ig4_load="YES" to /boot/loader.conf. I saw in 12-Current a checking https://github.com/freebsd/freebsd/...23d36aa#diff-9344fa2ebfa6399678c352b94e7c3cb7 ( Add support for i2c controllers on Skylake and Kaby Lake ).
Loading ig4 makes a little difference, it detects an "Intel Sunrise Point-LP I2C Controller". However the initialization failed with "ig4iic_pci0: controller error during attach-2".

Anyways, I'm don't know if I'm going in the right direction here, maybe it's totally unrelated.

Looking forward to get some advice.

PS:
If someone has the same laptop. You will need to modify your acpi battery driver to get battery initialization done. FreeBSD has as of today only support for "_BIF" but this laptop does not implement that in his DSDT. Instead you want to read from "_BIX". I got some inspiration on how to implement that from here. Works. https://github.com/openbsd/src/comm...f=split#diff-0ee599c4cd860206b8d64e11374d06d1.


----------



## ykla (Jul 23, 2018)

So could you tell me how to make it? I got the same error. 
"


pbp_jackd said:


> Instead you want to read from "_BIX". I got some inspiration on how to implement that from here. Works.


----------



## pbp_jackd (Jul 23, 2018)

Sure. Please consider the following as a quick hack to get it work.

1. In: /usr/src/sys/dev/acpica/acpiio.h  add the following struct


```
struct acpi_bix {
    uint8_t rev;            /* BIX Revision */
    uint32_t units;            /* Units (mW or mA). */
#define ACPI_BIX_UNITS_MW    0    /* Capacity in mWh, rate in mW. */
#define ACPI_BIX_UNITS_MA    1    /* Capacity in mAh, rate in mA. */
    uint32_t dcap;            /* Design Capacity */
    uint32_t lfcap;            /* Last Full capacity */
    uint32_t btech;            /* Battery Technology */
    uint32_t dvol;            /* Design voltage (mV) */
    uint32_t wcap;            /* WARN capacity */
    uint32_t lcap;            /* Low capacity */
    uint32_t ccnt;            /* Bix cycle count */
    uint32_t accu;            /* Bix accuracy */
    uint32_t maxs;            /* Bix max sample */
    uint32_t mins;            /* Bix min sample */
    uint32_t maxa;            /* Bix max average */
    uint32_t mina;            /* Bix min average */
    uint32_t gra1;            /* Granularity 1 (Warn to Low) */
    uint32_t gra2;            /* Granularity 2 (Full to Warn) */
    char model[ACPI_CMBAT_MAXSTRLEN];    /* model identifier */
    char serial[ACPI_CMBAT_MAXSTRLEN];    /* Serial number */
    char type[ACPI_CMBAT_MAXSTRLEN];    /* Type */
    char oeminfo[ACPI_CMBAT_MAXSTRLEN];    /* OEM information */
};
```

2.  Next, in: /usr/src/sys/dev/acpica/acpi_cmbat.c
2.1 I added a new buffer: bix_buffer
2.2 AcpiEvaluateObject will now read from _BIX and puts the result into our bix_buffer
2.3 ACPI_PKG_VALID(res, 20), we need to change that from 13 to 20 to pass the ckeck. _BIX has 20 elements.
2.4 now we need to adapt the *index* for the following lines, to copy the right data from the "BIX" to our "BIF" struct. E.g. "if (acpi_PkgInt32(res, *0*, &sc->bif.units) != 0)" changes to if (acpi_PkgInt32(res, *1*, &sc->bif.units) != 0). In "BIF" the "units" are the 1st element but in "BIX" its the 2nd. Just adapt the indexes for all the fields.


```
static void
acpi_cmbat_get_bif(void *arg)
{
    struct acpi_cmbat_softc *sc;
    ACPI_STATUS    as;
    ACPI_OBJECT    *res;
    ACPI_HANDLE    h;
    ACPI_BUFFER    bif_buffer;
    ACPI_BUFFER    bix_buffer;
    device_t dev;

    ACPI_SERIAL_ASSERT(cmbat);

    dev = arg;
    sc = device_get_softc(dev);
    h = acpi_get_handle(dev);
    bif_buffer.Pointer = NULL;
    bif_buffer.Length = ACPI_ALLOCATE_BUFFER;
    bix_buffer.Pointer = NULL;
    bix_buffer.Length = ACPI_ALLOCATE_BUFFER;

    as = AcpiEvaluateObject(h, "_BIX", NULL, &bix_buffer);
    if (ACPI_FAILURE(as)) {
    ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
            "error fetching current battery info -- %s\n",
            AcpiFormatException(as));
    goto end;
    }

    res = (ACPI_OBJECT *)bix_buffer.Pointer;
    if (!ACPI_PKG_VALID(res, 20)) {
    ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
            "battery info corrupted\n");
    goto end;
    }

    if (acpi_PkgInt32(res, 1, &sc->bif.units) != 0)
    goto end;
    if (acpi_PkgInt32(res, 2, &sc->bif.dcap) != 0)
    goto end;
    if (acpi_PkgInt32(res, 3, &sc->bif.lfcap) != 0)
    goto end;
    if (acpi_PkgInt32(res, 4, &sc->bif.btech) != 0)
    goto end;
    if (acpi_PkgInt32(res, 5, &sc->bif.dvol) != 0)
    goto end;
    if (acpi_PkgInt32(res, 6, &sc->bif.wcap) != 0)
    goto end;
    if (acpi_PkgInt32(res, 7, &sc->bif.lcap) != 0)
    goto end;
    if (acpi_PkgInt32(res, 14, &sc->bif.gra1) != 0)
    goto end;
    if (acpi_PkgInt32(res, 15, &sc->bif.gra2) != 0)
    goto end;
    if (acpi_PkgStr(res,  16, sc->bif.model, ACPI_CMBAT_MAXSTRLEN) != 0)
    goto end;
    if (acpi_PkgStr(res, 17, sc->bif.serial, ACPI_CMBAT_MAXSTRLEN) != 0)
    goto end;
    if (acpi_PkgStr(res, 18, sc->bif.type, ACPI_CMBAT_MAXSTRLEN) != 0)
    goto end;
    if (acpi_PkgStr(res, 19, sc->bif.oeminfo, ACPI_CMBAT_MAXSTRLEN) != 0)
    goto end;

end:
    if (bix_buffer.Pointer != NULL)
    AcpiOsFree(bix_buffer.Pointer);
    if (bif_buffer.Pointer != NULL)
    AcpiOsFree(bif_buffer.Pointer);
}
```

3. Buid the kernel
3.1 Create a new kernel configuration: `touch /usr/src/sys/amd64/conf/BATTERY`
3.2 open the file and add:

```
include GENERIC
```
3.2 build the kernel `make [B]-j16[/B] buildkernel [B]-DKERNFAST[/B] KERNCONF=BATTERY INSTKERNNAME=BATTERY`
3.2.1 remove the *-j16*  and/or *-DKERNFAST *if make is complaining
3.3 install the kernel `make -j16 installkernel -DKERNFAST KERNCONF=BATTERY INSTKERNNAME=BATTERY`
3.4 make your new kernel boot by default if you want*: *in /boot/loader.conf

```
kernel=BATTERY
```

Thats it.
Now your battery should show up.
JFYI:  I don't make use of all the extra fields in BIX. Making this work is a whole lot more work.
The moment you change the old *acpi_bif *struct, some programs which call into ACPIA will fail. E.g. "upower -d" and such.

However, I would be happy if you want to find a proper solution.
Also, my battery never shows 100% charged. At max it shows around 99 %. Not sure why. It could be my workaround has a bug or anything else. I just had no time to look into this.

I tested with 11.2 and 12 Current. Both worked.

Just curious. You also have the Matebook X Pro ?
I would love to partner up to find solutions for all the other issues. ( Touchpad and Nvidia card namely )
Let me know if you have other issues. I could share some of my tweeks.

I hope it works for you.

cu
Daniel


----------



## pbp_jackd (Aug 13, 2018)

Back to my original question about HID over I2C support.

There is some progress on the topic, documented here: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=221777
I think it would be great if more people test the suggested solution, so it can eventually become part of FreeBSD.


----------

