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 */

Reply via email to