This was much more straightforward than expected. - Replace an array with a LIST of allocated sensors. - Remove or rescope variables counting sensors. - Allocated sensors are always attached. - Drop an unnecessary size calculation.
Thanks. --david --- a/upd.c +++ b/upd.c @@ -23,6 +23,7 @@ #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/device.h> +#include <sys/queue.h> #include <sys/sensors.h> #include <dev/usb/hid.h> @@ -77,20 +78,18 @@ struct upd_report { struct upd_sensor { struct ksensor ksensor; struct hid_item hitem; - int attached; + LIST_ENTRY(upd_sensor) next; }; struct upd_softc { struct uhidev sc_hdev; - int sc_num_sensors; u_int sc_max_repid; - u_int sc_max_sensors; /* sensor framework */ struct ksensordev sc_sensordev; struct sensor_task *sc_sensortask; struct upd_report *sc_reports; - struct upd_sensor *sc_sensors; + LIST_HEAD(, upd_sensor) sc_sensors; }; int upd_match(struct device *, void *, void *); @@ -155,14 +154,14 @@ upd_attach(struct device *parent, struct struct hid_data *hdata; struct upd_usage_entry *entry; struct upd_sensor *sensor; + int num_sensors; int size; void *desc; sc->sc_hdev.sc_intr = upd_intr; sc->sc_hdev.sc_parent = uha->parent; sc->sc_reports = NULL; - sc->sc_sensors = NULL; - sc->sc_max_sensors = nitems(upd_usage_table); + LIST_INIT(&sc->sc_sensors); strlcpy(sc->sc_sensordev.xname, sc->sc_hdev.sc_dev.dv_xname, sizeof(sc->sc_sensordev.xname)); @@ -173,14 +172,11 @@ upd_attach(struct device *parent, struct sc->sc_reports = mallocarray(sc->sc_max_repid, sizeof(struct upd_report), M_USBDEV, M_WAITOK | M_ZERO); - sc->sc_sensors = mallocarray(sc->sc_max_sensors, - sizeof(struct upd_sensor), M_USBDEV, M_WAITOK | M_ZERO); - size = sc->sc_max_sensors * sizeof(struct upd_sensor); - sc->sc_num_sensors = 0; + num_sensors = 0; uhidev_get_report_desc(uha->parent, &desc, &size); for (hdata = hid_start_parse(desc, size, hid_feature); hid_get_item(hdata, &item) && - sc->sc_num_sensors < sc->sc_max_sensors; ) { + num_sensors < nitems(upd_usage_table); ) { DPRINTF(("upd: repid=%d\n", item.report_ID)); if (item.kind != hid_feature || item.report_ID < 0 || @@ -196,7 +192,8 @@ upd_attach(struct device *parent, struct if (sensor != NULL) continue; - sensor = &sc->sc_sensors[sc->sc_num_sensors]; + sensor = malloc(sizeof(struct upd_sensor), M_USBDEV, + M_WAITOK | M_ZERO); memcpy(&sensor->hitem, &item, sizeof(struct hid_item)); strlcpy(sensor->ksensor.desc, entry->usage_name, sizeof(sensor->ksensor.desc)); @@ -205,8 +202,8 @@ upd_attach(struct device *parent, struct sensor->ksensor.status = SENSOR_S_UNKNOWN; sensor->ksensor.value = 0; sensor_attach(&sc->sc_sensordev, &sensor->ksensor); - sensor->attached = 1; - sc->sc_num_sensors++; + LIST_INSERT_HEAD(&sc->sc_sensors, sensor, next); + num_sensors++; if (sc->sc_reports[item.report_ID].enabled) continue; @@ -216,7 +213,7 @@ upd_attach(struct device *parent, struct sc->sc_reports[item.report_ID].enabled = 1; } hid_end_parse(hdata); - DPRINTF(("upd: sc_num_sensors=%d\n", sc->sc_num_sensors)); + DPRINTF(("upd: num_sensors=%d\n", num_sensors)); sc->sc_sensortask = sensor_task_register(sc, upd_refresh, 6); if (sc->sc_sensortask == NULL) { @@ -235,7 +232,7 @@ upd_detach(struct device *self, int flag { struct upd_softc *sc = (struct upd_softc *)self; struct upd_sensor *sensor; - int i; + struct upd_sensor *t; if (sc->sc_sensortask != NULL) { wakeup(&sc->sc_sensortask); @@ -244,15 +241,14 @@ upd_detach(struct device *self, int flag sensordev_deinstall(&sc->sc_sensordev); - for (i = 0; i < sc->sc_num_sensors; i++) { - sensor = &sc->sc_sensors[i]; - if (sensor->attached) - sensor_detach(&sc->sc_sensordev, &sensor->ksensor); + LIST_FOREACH_SAFE(sensor, &sc->sc_sensors, next, t) { + sensor_detach(&sc->sc_sensordev, &sensor->ksensor); DPRINTF(("upd_detach: %s\n", sensor->ksensor.desc)); + LIST_REMOVE(sensor, next); + free(sensor, M_USBDEV, sizeof(struct upd_sensor)); } free(sc->sc_reports, M_USBDEV, 0); - free(sc->sc_sensors, M_USBDEV, 0); DPRINTF(("upd_detach: complete\n")); return (0); } @@ -306,10 +302,8 @@ struct upd_sensor * upd_lookup_sensor(struct upd_softc *sc, int page, int usage) { struct upd_sensor *sensor = NULL; - int i; - for (i = 0; i < sc->sc_num_sensors; i++) { - sensor = &sc->sc_sensors[i]; + LIST_FOREACH(sensor, &sc->sc_sensors, next) { if (page == HID_GET_USAGE_PAGE(sensor->hitem.usage) && usage == HID_GET_USAGE(sensor->hitem.usage)) return (sensor); @@ -324,14 +318,12 @@ upd_update_sensors(struct upd_softc *sc, struct upd_sensor *sensor; ulong hdata, batpres; ulong adjust; - int i; sensor = upd_lookup_sensor(sc, HUP_BATTERY, HUB_BATTERY_PRESENT); batpres = sensor ? sensor->ksensor.value : -1; - for (i = 0; i < sc->sc_num_sensors; i++) { - sensor = &sc->sc_sensors[i]; - if (!(sensor->hitem.report_ID == repid && sensor->attached)) + LIST_FOREACH(sensor, &sc->sc_sensors, next) { + if (sensor->hitem.report_ID != repid) continue; /* invalidate battery dependent sensors */