On Wed, Jan 27, 2016 at 05:20:59AM +0200, Sviatoslav Chagaev wrote: > On Sun, 10 Jan 2016 21:28:31 +0100 Joerg Jung wrote: > > On Sun, Jan 10, 2016 at 04:59:22AM +0200, Sviatoslav Chagaev wrote: > > > So below is a driver for TI LP8550. > ... > > > If there's any chance for it to be commited, please tell me what I need to > > > fix/improve to get it commited (so I don't have to reapply it every time I > > > upgrade). > > > > IMHO, instead of adding another driver to the mix, I would prefer this > > to be handled through the associated asmc(4) keys instead of accessing > > the chip directly. The SMC is supposed to be the central point for such > > manipulations. Unfortunately, the keys are not documented and need some > > non-trivial effort to be figured out. > > > > If this is not possible through asmc(4) and if your new driver improves > > the situation then I'm fine with importing it, but for now it is just > > worse. > > > > Using knowledge acquired from [1]
[1] contains some "wrong" (obsolete?) information, e.g. the Errors list. > and [2] made a diff, posted below for > reference, which adds: > * ioctl interface to asmc(4) to allow reading/writing of ``keys'' from > userspace; > * companion smcprobe(1) which reads/writes ``keys'' using the ioctl; Wow..., much effort for simple key dumping. Please, find below an (older/may not apply) diff which just dumps the keys directly from kernel into dmesg. Are you aware that keys can be all kind of types, e.g. structs? Have you seen the ASMC_INFO (0x13) command which might be used to determine the type? The key flags (read/write/atomic...) are mostly documented somewhere. > * smcdumpkeys(1): scans an SMC textual firmware file and dumps the ``key'' > table that it contains. Are you aware of the ASMC_INDEX (0x12) command, which can easily be used to just iterate ALL keys based on index? > Downloaded SMC FW [3], unpacked it using Google Drive and used smcdumpkeys(1) > + > smcprobe(1) to create the table of keys and their current values before > suspend > [4] and after wake up [5]. Diffed them [6], The diff approach is interesting... :) From your diff output I would try to play with IPBF, MSXk, SAPN, and DM0T. > filtering out keys which change over > time as they are probably sensors (some might have gotten through). If they start with: 'A'... usually ambient light sensor related, 'F'... fan sensors, 'T'... temperature sensors, 'P'... power related, 'V'... voltage sensors. > Tried modifying all keys whose names start with 'B': no effect. 'B'... is likely not "backlight" but "battery". > Tried modifying keys which are different after wake up: no effect. Please find a more exhaustive/descriptive list of keys here: http://web.archive.org/web/20151103144947/http://www.parhelia.ch/blog/statics/k3_keys.html Have you seen this: https://github.com/gcsgithub/smc_util it contains more details for the various structs. You may also want to have a look into the existing FreeBSD and Linux drivers. > [1] > https://reverse.put.as/wp-content/uploads/2015/12/D1_02_Alex_Ninjas_and_Harry_Potter.pdf > [2] > https://dev.inversepath.com/download/public/embedded_systems_exploitation.pdf > [3] https://support.apple.com/kb/DL1748?locale=en_US > [4] https://gist.github.com/S010/26145f4446fcc0b8a0d6#file-before_suspend-txt > [5] https://gist.github.com/S010/26145f4446fcc0b8a0d6#file-after_wakeup-txt > [6] > https://gist.github.com/S010/26145f4446fcc0b8a0d6#file-suspend_wakeup_key-diff Index: asmc.c =================================================================== RCS file: /cvs/src/sys/dev/isa/asmc.c,v retrieving revision 1.17 diff -u -p -r1.17 asmc.c --- asmc.c 12 Dec 2015 12:34:05 -0000 1.17 +++ asmc.c 12 Dec 2015 13:30:12 -0000 @@ -32,6 +32,8 @@ #include <dev/isa/isavar.h> #include <dev/wscons/wsconsio.h> +#define ASMC_DEBUG 1 + #define ASMC_BASE 0x300 /* SMC base address */ #define ASMC_IOSIZE 32 /* I/O region size 0x300-0x31f */ @@ -42,6 +44,7 @@ #define ASMC_READ 0x10 /* SMC read command */ #define ASMC_WRITE 0x11 /* SMC write command */ +#define ASMC_INDEX 0x12 /* SMC index command */ #define ASMC_INFO 0x13 /* SMC info/type command */ #define ASMC_RETRY 10 @@ -85,6 +88,9 @@ struct asmc_softc { }; int asmc_try(struct asmc_softc *, int, const char *, uint8_t *, uint8_t); +#ifdef ASMC_DEBUG +void asmc_dump(struct asmc_softc *, uint32_t); +#endif void asmc_init(void *); void asmc_refresh(void *); @@ -292,7 +298,9 @@ asmc_attach(struct device *parent, struc } printf(", %u key%s\n", ntohl(*(uint32_t *)buf), (ntohl(*(uint32_t *)buf) == 1) ? "" : "s"); - +#ifdef ASMC_DEBUG + asmc_dump(sc, ntohl(*(uint32_t *)buf)); +#endif /* keyboard backlight led is optional */ sc->sc_kbdled = buf[0] = 127, buf[1] = 0; if ((r = asmc_try(sc, ASMC_WRITE, "LKSB", buf, 2))) { @@ -479,25 +487,25 @@ asmc_command(struct asmc_softc *sc, int if (len > ASMC_MAXLEN) return 1; if (asmc_write(sc, ASMC_COMMAND, cmd)) - return 1; + return 2; for (i = 0; i < 4; i++) if (asmc_write(sc, ASMC_DATA, key[i])) - return 1; + return 3; if (asmc_write(sc, ASMC_DATA, len)) - return 1; - if (cmd == ASMC_READ || cmd == ASMC_INFO) { + return 4; + if (cmd == ASMC_READ || cmd == ASMC_INDEX || cmd == ASMC_INFO) { for (i = 0; i < len; i++) if (asmc_read(sc, ASMC_DATA, &buf[i])) - return 1; + return 5; for (i = 0; i < ASMC_MAXLEN; i++) /* sanity flush */ if (asmc_read(sc, ASMC_DATA, &n)) break; } else if (cmd == ASMC_WRITE) { for (i = 0; i < len; i++) if (asmc_write(sc, ASMC_DATA, buf[i])) - return 1; + return 6; } else - return 1; + return 7; return 0; } @@ -750,3 +758,40 @@ asmc_update(void *arg) if (sc->sc_init) task_add(sc->sc_taskq, &sc->sc_task_refresh); } + +#ifdef ASMC_DEBUG +void +asmc_dump(struct asmc_softc *sc, uint32_t len) +{ + uint8_t buf[4], key[4]; + uint32_t i; + int r, e; + + for (i = 0; i < len; i++, e = 0) { + *(uint32_t *)buf = htonl(i); + printf("%s: dump key[%u]", sc->sc_dev.dv_xname, i); +retry: + if ((r = asmc_try(sc, ASMC_INDEX, buf, key, 4))) { + printf(" failed (0x%x)\n", r); + continue; + } + if (!key[0] || !strncmp(key, "Pz0F", 4)) { + if (++e < ASMC_RETRY) { + delay(2 << 16); + goto retry; + } + printf(" *"); + } + printf(" '%c%c%c%c'", key[0], key[1], key[2], key[3]); + if (key[0] == 'T' || key[0] == 't') { + delay(2 << 16); + if (!(r = asmc_try(sc, ASMC_READ, key, buf, 2))) + printf(" t: %hd", + (((int16_t)ntohs(*(uint16_t *)buf)) >> 8)); + printf(" (0x%x)", r); + } + printf("\n"); + delay(2 << 16); + } +} +#endif