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:


Reply via email to