From 5dc076fc1c03d18d6137501a6417411ca6bd142a Mon Sep 17 00:00:00 2001 From: jung Date: Sun, 25 Oct 2015 19:26:43 +0000 Subject: [PATCH] refactor to use a taskq and postpone the long running initial sensor probing, also avoid excessive tsleep()s for updates within the sensor task, moreover this should fix some seldom seen 'comm collision' errors --- sys/dev/isa/asmc.c | 512 +++++++++++++++++++++++---------------------- 1 file changed, 264 insertions(+), 248 deletions(-) diff --git a/sys/dev/isa/asmc.c b/sys/dev/isa/asmc.c index 147fbe6cb76..5a9676e6c0b 100644 --- a/sys/dev/isa/asmc.c +++ b/sys/dev/isa/asmc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: asmc.c,v 1.11 2015/10/15 01:14:33 jsg Exp $ */ +/* $OpenBSD: asmc.c,v 1.12 2015/10/25 19:26:43 jung Exp $ */ /* * Copyright (c) 2015 Joerg Jung * @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -62,7 +63,13 @@ struct asmc_softc { bus_space_handle_t sc_ioh; struct asmc_prod *sc_prod; - uint8_t sc_lightlen; /* light data len */ + uint8_t sc_init; /* initialization done? */ + uint8_t sc_nfans; /* number of fans */ + uint8_t sc_lightlen; /* light data len */ + + struct taskq *sc_taskq; + struct task sc_task_init; + struct task sc_task_refresh; struct ksensor sc_sensor_temp[ASMC_MAXTEMP]; struct ksensor sc_sensor_fan[ASMC_MAXFAN]; @@ -72,7 +79,12 @@ struct asmc_softc { struct sensor_task *sc_sensor_task; }; -int asmc_init(struct asmc_softc *); +uint8_t asmc_status(struct asmc_softc *); +int asmc_try(struct asmc_softc *, int, const char *, uint8_t *, uint8_t); +void asmc_kbdled(struct asmc_softc *, uint8_t); + +void asmc_init(void *); +void asmc_refresh(void *); void asmc_update(void *); int asmc_match(struct device *, void *, void *); @@ -243,6 +255,8 @@ asmc_attach(struct device *parent, struct device *self, void *aux) { struct asmc_softc *sc = (struct asmc_softc *)self; struct isa_attach_args *ia = aux; + uint8_t buf[6]; + int i; if (bus_space_map(ia->ia_iot, ia->ia_iobase, ia->ia_iosize, 0, &sc->sc_ioh)) { @@ -251,23 +265,64 @@ asmc_attach(struct device *parent, struct device *self, void *aux) } sc->sc_iot = ia->ia_iot; - printf("\n"); + if (asmc_try(sc, ASMC_READ, "REV ", buf, 6)) { + printf(": revision failed (0x%x)\n", asmc_status(sc)); + bus_space_unmap(ia->ia_iot, ia->ia_iobase, ASMC_IOSIZE); + return; + } + printf(": rev %x.%x%x%x", buf[0], buf[1], buf[2], + ntohs(*(uint16_t *)buf + 4)); - strlcpy(sc->sc_sensor_dev.xname, sc->sc_dev.dv_xname, - sizeof(sc->sc_sensor_dev.xname)); + if (asmc_try(sc, ASMC_READ, "#KEY", buf, 4)) { + printf(", no of keys failed (0x%x)\n", asmc_status(sc)); + bus_space_unmap(ia->ia_iot, ia->ia_iobase, ASMC_IOSIZE); + return; + } + printf(", %u key%s", ntohl(*(uint32_t *)buf), + (ntohl(*(uint32_t *)buf) == 1) ? "" : "s"); - if (asmc_init(sc)) { - printf("%s: unable to initialize\n", sc->sc_dev.dv_xname); + if (!(sc->sc_taskq = taskq_create("asmc", 1, IPL_NONE, 0))) { + printf(", can't create task queue\n"); bus_space_unmap(ia->ia_iot, ia->ia_iobase, ASMC_IOSIZE); return; } + task_set(&sc->sc_task_init, asmc_init, sc); + task_set(&sc->sc_task_refresh, asmc_refresh, sc); - if (!(sc->sc_sensor_task = sensor_task_register(sc, asmc_update, 8))) { - printf("%s: unable to register task\n", sc->sc_dev.dv_xname); + strlcpy(sc->sc_sensor_dev.xname, sc->sc_dev.dv_xname, + sizeof(sc->sc_sensor_dev.xname)); + for (i = 0; i < ASMC_MAXTEMP; i++) { + sc->sc_sensor_temp[i].type = SENSOR_TEMP; + sc->sc_sensor_temp[i].flags |= SENSOR_FINVALID; + sc->sc_sensor_temp[i].flags |= SENSOR_FUNKNOWN; + } + for (i = 0; i < ASMC_MAXFAN; i++) { + sc->sc_sensor_fan[i].type = SENSOR_FANRPM; + sc->sc_sensor_fan[i].flags |= SENSOR_FINVALID; + sc->sc_sensor_fan[i].flags |= SENSOR_FUNKNOWN; + } + for (i = 0; i < ASMC_MAXLIGHT; i++) { + sc->sc_sensor_light[i].type = SENSOR_LUX; + sc->sc_sensor_light[i].flags |= SENSOR_FINVALID; + sc->sc_sensor_light[i].flags |= SENSOR_FUNKNOWN; + } + for (i = 0; i < ASMC_MAXMOTION; i++) { + sc->sc_sensor_motion[i].type = SENSOR_ACCEL; + sc->sc_sensor_motion[i].flags |= SENSOR_FINVALID; + sc->sc_sensor_motion[i].flags |= SENSOR_FUNKNOWN; + } + if (!(sc->sc_sensor_task = sensor_task_register(sc, asmc_update, 5))) { + printf(", unable to register sensor task\n"); + taskq_destroy(sc->sc_taskq); bus_space_unmap(ia->ia_iot, ia->ia_iobase, ASMC_IOSIZE); return; } + printf("\n"); + + asmc_kbdled(sc, 127); + sensordev_install(&sc->sc_sensor_dev); + task_add(sc->sc_taskq, &sc->sc_task_init); } int @@ -276,27 +331,27 @@ asmc_detach(struct device *self, int flags) struct asmc_softc *sc = (struct asmc_softc *)self; int i; - wakeup(&sc->sc_sensor_task); - sensordev_deinstall(&sc->sc_sensor_dev); if (sc->sc_sensor_task) sensor_task_unregister(sc->sc_sensor_task); - + sensordev_deinstall(&sc->sc_sensor_dev); for (i = 0; i < ASMC_MAXMOTION; i++) sensor_detach(&sc->sc_sensor_dev, &sc->sc_sensor_motion[i]); - for (i = 0; i < ASMC_MAXLIGHT; i++) sensor_detach(&sc->sc_sensor_dev, &sc->sc_sensor_light[i]); - for (i = 0; i < ASMC_MAXFAN; i++) sensor_detach(&sc->sc_sensor_dev, &sc->sc_sensor_fan[i]); - for (i = 0; i < ASMC_MAXTEMP; i++) sensor_detach(&sc->sc_sensor_dev, &sc->sc_sensor_temp[i]); + if (sc->sc_taskq) { + task_del(sc->sc_taskq, &sc->sc_task_refresh); + task_del(sc->sc_taskq, &sc->sc_task_init); + taskq_destroy(sc->sc_taskq); + } return 0; } -static uint8_t +uint8_t asmc_status(struct asmc_softc *sc) { return bus_space_read_1(sc->sc_iot, sc->sc_ioh, ASMC_STATUS); @@ -309,7 +364,7 @@ asmc_wait(struct asmc_softc *sc, uint8_t m) for (us = (2 << 4); us < (2 << 16); us *= 2) { /* wait up to 128 ms */ (!sc->sc_sensor_task) ? delay(us) : - tsleep(&sc->sc_sensor_task, 0, "asmc", + tsleep(&sc->sc_taskq, 0, "asmc", (us * hz + 999999) / 1000000 + 1); if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, ASMC_COMMAND) & m) return 1; @@ -320,13 +375,9 @@ asmc_wait(struct asmc_softc *sc, uint8_t m) static int asmc_write(struct asmc_softc *sc, uint8_t off, uint8_t val) { - int i; - - for (i = 0; i < ASMC_RETRY; i++) { - bus_space_write_1(sc->sc_iot, sc->sc_ioh, off, val); - if (asmc_wait(sc, 0x04)) /* write accepted? */ - return 0; - } + bus_space_write_1(sc->sc_iot, sc->sc_ioh, off, val); + if (asmc_wait(sc, 0x04)) /* write accepted? */ + return 0; return 1; } @@ -372,7 +423,7 @@ asmc_command(struct asmc_softc *sc, int cmd, const char *key, uint8_t *buf, return 0; } -static int +int asmc_try(struct asmc_softc *sc, int cmd, const char *key, uint8_t *buf, uint8_t len) { @@ -384,279 +435,244 @@ asmc_try(struct asmc_softc *sc, int cmd, const char *key, uint8_t *buf, return 1; } -static int -asmc_temps(struct asmc_softc *sc, uint8_t *n) +static uint32_t +asmc_uk(uint8_t *buf) { - uint8_t buf[2], s; - int i, j; + /* spe78: floating point, signed, 7 bits exponent, 8 bits fraction */ + return (((int16_t)ntohs(*(uint16_t *)buf)) >> 8) * 1000000 + 273150000; +} - for (i = 0, *n = 0; i < ASMC_MAXTEMP; i++) { - sc->sc_sensor_temp[i].type = SENSOR_TEMP; - sc->sc_sensor_temp[i].flags |= SENSOR_FINVALID; - if (!sc->sc_prod->pr_temp[i]) - continue; - - s = 0; - if (asmc_try(sc, ASMC_READ, sc->sc_prod->pr_temp[i], buf, 2) && - (s = asmc_status(sc)) != ASMC_NOTFOUND) { - printf(", read %s failed (0x%x)", - sc->sc_prod->pr_temp[i], s); - continue; /*return 1;*/ - } - if (s == ASMC_NOTFOUND) - continue; - - (*n)++; - strlcpy(sc->sc_sensor_temp[i].desc, sc->sc_prod->pr_temp[i], - sizeof(sc->sc_sensor_temp[i].desc)); - for (j = 0; asmc_temp_desc[j][0]; j++) - if (!strcmp(asmc_temp_desc[j][0], - sc->sc_prod->pr_temp[i])) - break; - if (asmc_temp_desc[j][0]) { - strlcat(sc->sc_sensor_temp[i].desc, " ", - sizeof(sc->sc_sensor_temp[i].desc)); - strlcat(sc->sc_sensor_temp[i].desc, - asmc_temp_desc[j][1], - sizeof(sc->sc_sensor_temp[i].desc)); - } - sc->sc_sensor_temp[i].flags &= ~SENSOR_FINVALID; - sensor_attach(&sc->sc_sensor_dev, &sc->sc_sensor_temp[i]); - } - return 0; +static uint16_t +asmc_rpm(uint8_t *buf) +{ + /* fpe2: floating point, unsigned, 14 bits exponent, 2 bits fraction */ + return ntohs(*(uint16_t *)buf) >> 2; +} + +static uint32_t +asmc_lux(uint8_t *buf, uint8_t lightlen) +{ + /* newer macbooks report a 10 bit big endian value */ + return (lightlen == 10) ? + /* fp18.14: floating point, 18 bits exponent, 14 bits fraction */ + (ntohl(*(uint32_t *)(buf + 6)) >> 14) * 1000000 : + /* + * todo: calculate lux from ADC raw data + * buf[1] true/false for high/low gain chan reads + * chan 0: ntohs(*(uint16_t *)(buf + 2)); + * chan 1: ntohs(*(uint16_t *)(buf + 4)); + */ + ntohs(*(uint16_t *)(buf + 2)) * 1000000; } static int -asmc_fans(struct asmc_softc *sc, uint8_t *n) +asmc_temp(struct asmc_softc *sc, uint8_t idx) { - char key[5]; - uint8_t buf[16], *end; + uint8_t buf[2]; int i; - *n = 0; - if (asmc_try(sc, ASMC_READ, "FNum", buf, 1)) { - printf(", read FNum failed (0x%x)", asmc_status(sc)); + if (asmc_try(sc, ASMC_READ, sc->sc_prod->pr_temp[idx], buf, 2)) return 1; - } - *n = buf[0]; + sc->sc_sensor_temp[idx].value = asmc_uk(buf); + sc->sc_sensor_temp[idx].flags &= ~SENSOR_FUNKNOWN; - for (i = 0; i < ASMC_MAXFAN; i++) { - sc->sc_sensor_fan[i].type = SENSOR_FANRPM; - sc->sc_sensor_fan[i].flags |= SENSOR_FINVALID; - if (i >= *n) - continue; + if (sc->sc_init) + return 0; - snprintf(key, sizeof(key), "F%dID", i); - if (asmc_try(sc, ASMC_READ, key, buf, 16)) { - printf(", read %s failed (0x%x)", key, - asmc_status(sc)); - return 1; - } - end = buf + 4 + strlen((char *)buf + 4) - 1; - while (buf + 4 < end && *end == ' ') /* trim trailing spaces */ - *end-- = '\0'; - strlcpy(sc->sc_sensor_fan[i].desc, buf + 4, - sizeof(sc->sc_sensor_fan[i].desc)); - if (buf[2] < nitems(asmc_fan_loc)) { - strlcat(sc->sc_sensor_fan[i].desc, " ", - sizeof(sc->sc_sensor_fan[i].desc)); - strlcat(sc->sc_sensor_fan[i].desc, - asmc_fan_loc[buf[2]], - sizeof(sc->sc_sensor_fan[i].desc)); - } - sc->sc_sensor_fan[i].flags &= ~SENSOR_FINVALID; - sensor_attach(&sc->sc_sensor_dev, &sc->sc_sensor_fan[i]); + strlcpy(sc->sc_sensor_temp[idx].desc, sc->sc_prod->pr_temp[idx], + sizeof(sc->sc_sensor_temp[idx].desc)); + for (i = 0; asmc_temp_desc[i][0]; i++) + if (!strcmp(asmc_temp_desc[i][0], sc->sc_prod->pr_temp[idx])) + break; + if (asmc_temp_desc[i][0]) { + strlcat(sc->sc_sensor_temp[idx].desc, " ", + sizeof(sc->sc_sensor_temp[idx].desc)); + strlcat(sc->sc_sensor_temp[idx].desc, asmc_temp_desc[i][1], + sizeof(sc->sc_sensor_temp[idx].desc)); } + sc->sc_sensor_temp[idx].flags &= ~SENSOR_FINVALID; + sensor_attach(&sc->sc_sensor_dev, &sc->sc_sensor_temp[idx]); return 0; } static int -asmc_lights(struct asmc_softc *sc, uint8_t *n) +asmc_fan(struct asmc_softc *sc, uint8_t idx) { char key[5]; - uint8_t buf[6], s; - int i; + uint8_t buf[16], *end; - for (i = 0, *n = 0; i < ASMC_MAXLIGHT; i++) { - sc->sc_sensor_light[i].type = SENSOR_LUX; - sc->sc_sensor_light[i].flags |= SENSOR_FINVALID; - s = 0; - snprintf(key, sizeof(key), "ALV%d", i); - if (asmc_try(sc, ASMC_READ, key, buf, 6) && - (s = asmc_status(sc)) != ASMC_NOTFOUND) { - printf(", read %s failed (0x%x)", key, s); - return 1; - } - if (s == ASMC_NOTFOUND || !buf[0]) /* valid data? */ - continue; - - (*n)++; - if (!sc->sc_lightlen) { - if (asmc_try(sc, ASMC_INFO, key, buf, 6)) { - printf(", info %s failed (0x%x)", key, - asmc_status(sc)); - return 1; - } - sc->sc_lightlen = buf[0]; - } - strlcpy(sc->sc_sensor_light[i].desc, asmc_light_desc[i], - sizeof(sc->sc_sensor_light[i].desc)); - sc->sc_sensor_light[i].flags &= ~SENSOR_FINVALID; - sensor_attach(&sc->sc_sensor_dev, &sc->sc_sensor_light[i]); + snprintf(key, sizeof(key), "F%dAc", idx); + if (asmc_try(sc, ASMC_READ, key, buf, 2)) + return 1; + sc->sc_sensor_fan[idx].value = asmc_rpm(buf); + sc->sc_sensor_fan[idx].flags &= ~SENSOR_FUNKNOWN; + + if (sc->sc_init) + return 0; + + snprintf(key, sizeof(key), "F%dID", idx); + if (asmc_try(sc, ASMC_READ, key, buf, 16)) + return 1; + end = buf + 4 + strlen((char *)buf + 4) - 1; + while (buf + 4 < end && *end == ' ') /* trim trailing spaces */ + *end-- = '\0'; + strlcpy(sc->sc_sensor_fan[idx].desc, buf + 4, + sizeof(sc->sc_sensor_fan[idx].desc)); + if (buf[2] < nitems(asmc_fan_loc)) { + strlcat(sc->sc_sensor_fan[idx].desc, " ", + sizeof(sc->sc_sensor_fan[idx].desc)); + strlcat(sc->sc_sensor_fan[idx].desc, asmc_fan_loc[buf[2]], + sizeof(sc->sc_sensor_fan[idx].desc)); } + sc->sc_sensor_fan[idx].flags &= ~SENSOR_FINVALID; + sensor_attach(&sc->sc_sensor_dev, &sc->sc_sensor_fan[idx]); return 0; } static int -asmc_motions(struct asmc_softc *sc, uint8_t *n) +asmc_light(struct asmc_softc *sc, uint8_t idx) { - uint8_t buf[2], s; - int i; + char key[5]; + uint8_t buf[10]; - *n = 0; - s = 0; - if (asmc_try(sc, ASMC_READ, "MOCN", buf, 2) && - (s = asmc_status(sc)) != ASMC_NOTFOUND) { - printf(", read MOCN failed (0x%x)", s); - return 1; + snprintf(key, sizeof(key), "ALV%d", idx); + if (!sc->sc_lightlen) { + if (asmc_try(sc, ASMC_INFO, key, buf, 6)) + return 1; + if ((sc->sc_lightlen = buf[0]) > 10) + return 1; } - if (s == ASMC_NOTFOUND) + if (asmc_try(sc, ASMC_READ, key, buf, sc->sc_lightlen)) + return 1; + if (!buf[0]) /* valid data? */ return 0; + sc->sc_sensor_light[idx].value = asmc_lux(buf, sc->sc_lightlen); + sc->sc_sensor_light[idx].flags &= ~SENSOR_FUNKNOWN; - *n = 1; -#if 0 /* todo: initialize sudden motion sensors and setup interrupt handling */ - buf[0] = 0xe0, buf[1] = 0xf8; - if (asmc_try(sc, ASMC_WRITE, "MOCN", buf, 2)) { - printf(", write MOCN failed (0x%x)", asmc_status(sc)); + if (sc->sc_init) return 0; - } -#endif - for (i = 0; i < ASMC_MAXMOTION; i++) { - sc->sc_sensor_motion[i].type = SENSOR_ACCEL; - sc->sc_sensor_motion[i].flags |= SENSOR_FINVALID; -#if 0 /* todo: setup and attach sensors and description */ - strlcpy(sc->sc_sensor_motion[i].desc, 120 + i, /* x, y, z */ - sizeof(sc->sc_sensor_motion[i].desc)); - strlcat(sc->sc_sensor_motion[i].desc, "-axis", - sizeof(sc->sc_sensor_motion[i].desc)); - sc->sc_sensor_motion[i].flags &= ~SENSOR_FINVALID; - sensor_attach(&sc->sc_sensor_dev, &sc->sc_sensor_motion[i]); -#endif - } + strlcpy(sc->sc_sensor_light[idx].desc, asmc_light_desc[idx], + sizeof(sc->sc_sensor_light[idx].desc)); + sc->sc_sensor_light[idx].flags &= ~SENSOR_FINVALID; + sensor_attach(&sc->sc_sensor_dev, &sc->sc_sensor_light[idx]); return 0; } -int -asmc_init(struct asmc_softc *sc) +#if 0 /* todo: implement motion sensors update and initialization */ +static int +asmc_motion(struct asmc_softc *sc, uint8_t idx) { - uint8_t buf[6], n, s; - - printf("%s:", sc->sc_dev.dv_xname); + char key[5]; + uint8_t buf[2]; - if (asmc_try(sc, ASMC_READ, "REV ", buf, 6)) { - printf(" revision failed (0x%x)\n", asmc_status(sc)); + snprintf(key, sizeof(key), "MO_%c", 88 + idx); /* X, Y, Z */ + if (asmc_try(sc, ASMC_READ, key, buf, 2)) return 1; - } - printf(" rev %x.%x%x%x", buf[0], buf[1], buf[2], - ntohs(*(uint16_t *)buf + 4)); - - if (asmc_try(sc, ASMC_READ, "#KEY", buf, 4)) { - printf(", no of keys failed (0x%x)\n", asmc_status(sc)); - return 1; - } - printf(", %u key%s", ntohl(*(uint32_t *)buf), - (ntohl(*(uint32_t *)buf) == 1) ? "" : "s"); + sc->sc_sensor_motion[idx].value = 0; + sc->sc_sensor_motion[idx].flags &= ~SENSOR_FUNKNOWN; - if (asmc_temps(sc, &n)) { /* temperature sensors depend on product */ - printf(", temperature sensors failed\n"); - return 1; - } - printf(", %u temperature%s", n, (n == 1) ? "" : "s"); + if (sc->sc_init) + return 0; - if (asmc_fans(sc, &n)) { /* fan sensors depend on product */ - printf(", fan sensors failed\n"); - return 1; - } - printf(", %u fan%s", n, (n == 1) ? "" : "s"); + /* todo: setup and attach sensors and description */ + strlcpy(sc->sc_sensor_motion[idx].desc, 120 + idx, /* x, y, z */ + sizeof(sc->sc_sensor_motion[idx].desc)); + strlcat(sc->sc_sensor_motion[idx].desc, "-axis", + sizeof(sc->sc_sensor_motion[idx].desc)); + sc->sc_sensor_motion[idx].flags &= ~SENSOR_FINVALID; + sensor_attach(&sc->sc_sensor_dev, &sc->sc_sensor_motion[idx]); + return 0; +} +#endif - if (asmc_lights(sc, &n)) { /* l/r light sensors are optional */ - printf(", light sensors failed\n"); - return 1; - } - printf("%s", n ? ", lights" : ""); +void +asmc_kbdled(struct asmc_softc *sc, uint8_t b) +{ + uint8_t buf[2] = { b, 0 }, s; - if (asmc_motions(sc, &n)) { /* motion sensors are optional */ - printf(", sudden motion sensors failed\n"); - return 1; + /* keyboard backlight led is optional */ + if (asmc_try(sc, ASMC_WRITE, "LKSB", buf, 2)) { + if ((s = asmc_status(sc)) != ASMC_NOTFOUND) + printf("%s: keyboard backlight failed (0x%x)\n", + sc->sc_dev.dv_xname, s); } - printf("%s", n ? ", motions" : ""); +} - buf[0] = 127, buf[1] = 0; /* keyboard backlight led is optional */ - if (asmc_try(sc, ASMC_WRITE, "LKSB", buf, 2) && - (s = asmc_status(sc)) != ASMC_NOTFOUND) { - printf(", keyboard backlight failed (0x%x)\n", s); - return 1; - } - printf("\n"); +void +asmc_init(void *arg) +{ + struct asmc_softc *sc = arg; + uint8_t buf[2], s; + int i; - return 0; + /* number of temperature sensors depends on product */ + for (i = 0; sc->sc_prod->pr_temp[i] && i < ASMC_MAXTEMP; i++) + if (asmc_temp(sc, i) && (s = asmc_status(sc)) != ASMC_NOTFOUND) + printf("%s: read temp %d failed (0x%x)\n", + sc->sc_dev.dv_xname, i, s); + /* number of fan sensors depends on product */ + if (asmc_try(sc, ASMC_READ, "FNum", buf, 1)) + printf("%s: read FNum failed (0x%x)\n", sc->sc_dev.dv_xname, + asmc_status(sc)); + else + sc->sc_nfans = buf[0]; + for (i = 0; i < sc->sc_nfans && i < ASMC_MAXFAN; i++) + if (asmc_fan(sc, i) && (s = asmc_status(sc)) != ASMC_NOTFOUND) + printf("%s: read fan %d failed (0x%x)\n", + sc->sc_dev.dv_xname, i, s); + /* left and right light sensors are optional */ + for (i = 0; i < ASMC_MAXLIGHT; i++) + if (asmc_light(sc, i) && + (s = asmc_status(sc)) != ASMC_NOTFOUND) + printf("%s: read light %d failed (0x%x)\n", + sc->sc_dev.dv_xname, i, s); + /* motion sensors are optional */ + if (asmc_try(sc, ASMC_READ, "MOCN", buf, 2) && + (s = asmc_status(sc)) != ASMC_NOTFOUND) + printf("%s: read MOCN failed (0x%x)\n", + sc->sc_dev.dv_xname, s); +#if 0 /* todo: initialize sudden motion sensors and setup interrupt handling */ + buf[0] = 0xe0, buf[1] = 0xf8; + if (asmc_try(sc, ASMC_WRITE, "MOCN", buf, 2)) + printf("%s write MOCN failed (0x%x)\n", sc->sc_dev.dv_xname, + asmc_status(sc)); + for (i = 0; i < ASMC_MAXMOTION; i++) + if (asmc_motion(sc, i) && + (s = asmc_status(sc)) != ASMC_NOTFOUND) + printf("%s: read motion %d failed (0x%x)\n", + sc->sc_dev.dv_xname, i, s); +#endif + sc->sc_init = 1; } void -asmc_update(void *arg) +asmc_refresh(void *arg) { struct asmc_softc *sc = arg; - char key[5]; - uint8_t buf[10]; int i; - /* spe78: floating point, signed, 7 bits exponent, 8 bits fraction */ - for (i = 0; i < ASMC_MAXTEMP; i++) { - if (!(sc->sc_sensor_temp[i].flags & SENSOR_FINVALID) && - !asmc_try(sc, ASMC_READ, sc->sc_prod->pr_temp[i], buf, 2)) - sc->sc_sensor_temp[i].value = - (((int16_t)ntohs(*(uint16_t *)buf)) >> 8) * - 1000000 + 273150000; - } - - /* fpe2: floating point, unsigned, 14 bits exponent, 2 bits fraction */ - for (i = 0; i < ASMC_MAXFAN; i++) { - snprintf(key, sizeof(key), "F%dAc", i); - if (!(sc->sc_sensor_fan[i].flags & SENSOR_FINVALID) && - !asmc_try(sc, ASMC_READ, key, buf, 2)) - sc->sc_sensor_fan[i].value = - ntohs(*(uint16_t *)buf) >> 2; - } + for (i = 0; sc->sc_prod->pr_temp[i] && i < ASMC_MAXTEMP; i++) + if (!(sc->sc_sensor_temp[i].flags & SENSOR_FINVALID)) + asmc_temp(sc, i); + for (i = 0; i < sc->sc_nfans && i < ASMC_MAXFAN; i++) + if (!(sc->sc_sensor_fan[i].flags & SENSOR_FINVALID)) + asmc_fan(sc, i); + for (i = 0; i < ASMC_MAXLIGHT; i++) + if (!(sc->sc_sensor_light[i].flags & SENSOR_FINVALID)) + asmc_light(sc, i); +#if 0 + for (i = 0; i < ASMC_MAXMOTION; i++) + if (!(sc->sc_sensor_motion[i].flags & SENSOR_FINVALID)) + asmc_motion(sc, i); +#endif +} - for (i = 0; i < ASMC_MAXLIGHT; i++) { - snprintf(key, sizeof(key), "ALV%d", i); - if (!(sc->sc_sensor_light[i].flags & SENSOR_FINVALID) && - !asmc_try(sc, ASMC_READ, key, buf, sc->sc_lightlen)) - /* newer macbooks report an 10 bit big endian value */ - sc->sc_sensor_light[i].value = - (sc->sc_lightlen == 10) ? - /* - * fp18.14: floating point, - * 18 bits exponent, 14 bits fraction - */ - (ntohl(*(uint32_t *)(buf + 6)) >> 14) * 1000000 : - /* - * todo: calculate lux from ADC raw data: - * buf[1] true/false for high/low gain chan reads - * chan 0: ntohs(*(uint16_t *)(buf + 2)); - * chan 1: ntohs(*(uint16_t *)(buf + 4)); - */ - ((sc->sc_sensor_light[i].flags |= - SENSOR_FUNKNOWN), 0); - } +void +asmc_update(void *arg) +{ + struct asmc_softc *sc = arg; -#if 0 /* todo: implement motion sensors update */ - for (i = 0; i < ASMC_MAXMOTION; i++) { - snprintf(key, sizeof(key), "MO_%c", 88 + i); /* X, Y, Z */ - if (!(sc->sc_sensor_motion[i].flags & SENSOR_FINVALID) && - !asmc_try(sc, ASMC_READ, key, buf, 2)) - sc->sc_sensor_motion[i].value = 0; - } -#endif + if (sc->sc_init) + task_add(sc->sc_taskq, &sc->sc_task_refresh); } -- 2.20.1