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: