Features of this diff: - All upd(4) reports are queried asynchronously - Use pending status to prevent duplicate usb queries - No apparent changes from end-user point of view
Note: depends on the previous upd(4) LIST diff, not yet committed. As usual, feedback and comments are welcome. --david --- a/upd.c +++ b/upd.c @@ -73,17 +73,20 @@ static struct upd_usage_entry upd_usage_ struct upd_report { size_t size; int enabled; + int pending; }; struct upd_sensor { struct ksensor ksensor; struct hid_item hitem; LIST_ENTRY(upd_sensor) next; + int pending; }; struct upd_softc { struct uhidev sc_hdev; u_int sc_max_repid; + char sc_buf[256]; /* sensor framework */ struct ksensordev sc_sensordev; @@ -98,7 +101,9 @@ void upd_attach(struct device *, struct int upd_detach(struct device *, int); void upd_refresh(void *); -void upd_update_sensors(struct upd_softc *, uint8_t *, unsigned int, int); +void upd_request_sensor_refresh(struct upd_softc *, struct upd_sensor *); +void upd_update_report_cb(void *, int, void *, int); +void upd_update_sensor(struct upd_softc *, struct upd_sensor *, uint8_t *, int); void upd_intr(struct uhidev *, void *, uint); struct upd_usage_entry *upd_lookup_usage_entry(const struct hid_item *); struct upd_sensor *upd_lookup_sensor(struct upd_softc *, int, int); @@ -258,30 +263,68 @@ void upd_refresh(void *arg) { struct upd_softc *sc = (struct upd_softc *)arg; - struct upd_report *report; - uint8_t buf[256]; - int repid, actlen; + struct upd_sensor *sensor; - for (repid = 0; repid < sc->sc_max_repid; repid++) { - report = &sc->sc_reports[repid]; - if (!report->enabled) - continue; + LIST_FOREACH(sensor, &sc->sc_sensorlist, next) + upd_request_sensor_refresh(sc, sensor); +} - memset(buf, 0x0, sizeof(buf)); - actlen = uhidev_get_report(sc->sc_hdev.sc_parent, - UHID_FEATURE_REPORT, repid, buf, report->size); +void +upd_request_sensor_refresh(struct upd_softc *sc, struct upd_sensor *sensor) +{ + struct upd_report *report; + int repid; - if (actlen == -1) { - DPRINTF(("upd: failed to get report id=%02x\n", repid)); - continue; - } + repid = sensor->hitem.report_ID; + report = &sc->sc_reports[repid]; + if (sensor->pending) + DPRINTF(("%s: sensor %s (repid=%d) still pending\n", + sc->sc_sensordev.xname, sensor->ksensor.desc, repid)); + else if (report->pending) + /* already requested */ + sensor->pending = 1; + else if (uhidev_get_report_async(sc->sc_hdev.sc_parent, + UHID_FEATURE_REPORT, repid, sc->sc_buf, report->size, + sc, upd_update_report_cb) > 0) { + DPRINTF(("%s: %s requests repid %d\n", + sc->sc_sensordev.xname, sensor->ksensor.desc, repid)); + report->pending = 1; + sensor->pending = 1; + } else { + DPRINTF(("%s: failed to request %s (repid=%d)\n", + sc->sc_sensordev.xname, sensor->ksensor.desc, repid)); + sensor->ksensor.status = SENSOR_S_UNKNOWN; + sensor->ksensor.flags |= SENSOR_FINVALID; + } +} - /* Deal with buggy firmwares. */ - if (actlen < report->size) - report->size = actlen; +void +upd_update_report_cb(void *priv, int repid, void *data, int len) +{ + struct upd_softc *sc = priv; + struct upd_report *report; + struct upd_sensor *sensor; - upd_update_sensors(sc, buf, report->size, repid); + /* handle buggy firmware */ + report = &sc->sc_reports[repid]; + if (len > 0 && report->size != len) { + DPRINTF(("%s: adjusting size of repid %d\n", + sc->sc_sensordev.xname, repid)); + report->size = len; } + + LIST_FOREACH(sensor, &sc->sc_sensorlist, next) { + if (sensor->hitem.report_ID == repid) { + if (len > 0) + upd_update_sensor(sc, sensor, data, len); + else { + sensor->ksensor.status = SENSOR_S_UNKNOWN; + sensor->ksensor.flags |= SENSOR_FINVALID; + } + sensor->pending = 0; + } + } + report->pending = 0; } struct upd_usage_entry * @@ -313,32 +356,22 @@ upd_lookup_sensor(struct upd_softc *sc, } void -upd_update_sensors(struct upd_softc *sc, uint8_t *buf, unsigned int len, - int repid) +upd_update_sensor(struct upd_softc *sc, struct upd_sensor *sensor, + uint8_t *buf, int len) { - struct upd_sensor *sensor; + struct upd_sensor *battery; ulong hdata, batpres; ulong adjust; - sensor = upd_lookup_sensor(sc, HUP_BATTERY, HUB_BATTERY_PRESENT); - batpres = sensor ? sensor->ksensor.value : -1; - - LIST_FOREACH(sensor, &sc->sc_sensorlist, next) { - if (sensor->hitem.report_ID != repid) - continue; - - /* invalidate battery dependent sensors */ - if (HID_GET_USAGE_PAGE(sensor->hitem.usage) == HUP_BATTERY && - batpres <= 0) { - /* exception to the battery sensor itself */ - if (HID_GET_USAGE(sensor->hitem.usage) != - HUB_BATTERY_PRESENT) { - sensor->ksensor.status = SENSOR_S_UNKNOWN; - sensor->ksensor.flags |= SENSOR_FINVALID; - continue; - } - } + battery = upd_lookup_sensor(sc, HUP_BATTERY, HUB_BATTERY_PRESENT); + batpres = battery ? battery->ksensor.value : -1; + /* invalidate battery dependent sensors, except for battery itself */ + if (HID_GET_USAGE_PAGE(sensor->hitem.usage) == HUP_BATTERY && + sensor != battery && batpres <= 0) { + sensor->ksensor.flags |= SENSOR_FINVALID; + sensor->ksensor.status = SENSOR_S_UNKNOWN; + } else { switch (HID_GET_USAGE(sensor->hitem.usage)) { case HUB_REL_STATEOF_CHARGE: case HUB_ABS_STATEOF_CHARGE: