On Tue, Feb 09, 2021 at 08:34:00AM +0100, Anton Lindqvist wrote: > Hi, > > On Mon, Feb 08, 2021 at 02:50:39PM -0800, Anindya Mukherjee wrote: > > Hi, I have a Logitech M570 which seems to be handled by this new driver. > > However I don't see any battery level information. > > > > dmesg: > > uhidpp0 at uhidev4 device 1 mouse "M570" serial ef-81-ff-80 > > > > sysctl kern.version: > > kern.version=OpenBSD 6.8-current (GENERIC.MP) #313: Fri Feb 5 18:31:44 MST > > 2021 > > dera...@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP > > > > hw.sensors.uhidpp0 does not seem to exist. > > > > Regards, > > Anindya > > > > Could you try the following diff and send me the complete dmesg. I've > also prepared an amd64 kernel with the patch applied: > > https://www.basename.se/tmp/bsd.uhidpp.battery
Thanks! I'll try it as soon as I can and report back. > > diff --git sys/dev/usb/uhidpp.c sys/dev/usb/uhidpp.c > index b041d86fecd..27f6137ec06 100644 > --- sys/dev/usb/uhidpp.c > +++ sys/dev/usb/uhidpp.c > @@ -29,7 +29,7 @@ > #include <dev/usb/usbdevs.h> > #include <dev/usb/uhidev.h> > > -/* #define UHIDPP_DEBUG */ > +#define UHIDPP_DEBUG > #ifdef UHIDPP_DEBUG > > #define DPRINTF(x...) do { \ > @@ -84,12 +84,16 @@ int uhidpp_debug = 1; > #define HIDPP_GET_LONG_REGISTER 0x83 > > #define HIDPP_REG_ENABLE_REPORTS 0x00 > +#define HIDPP_REG_BATTERY_STATUS 0x07 > #define HIDPP_REG_PAIRING_INFORMATION 0xb5 > > #define HIDPP_NOTIF_DEVICE_BATTERY_STATUS (1 << 4) > #define HIDPP_NOTIF_RECEIVER_WIRELESS (1 << 0) > #define HIDPP_NOTIF_RECEIVER_SOFTWARE_PRESENT (1 << 3) > > +/* Number of battery levels supported by HID++ 1.0 devices. */ > +#define HIDPP_BATTERY_NLEVELS 7 > + > /* HID++ 1.0 error codes. */ > #define HIDPP_ERROR 0x8f > #define HIDPP_ERROR_SUCCESS 0x00 > @@ -112,7 +116,6 @@ int uhidpp_debug = 1; > * greater than zero which is reserved for notifications. > */ > #define HIDPP_SOFTWARE_ID 0x01 > -#define HIDPP_SOFTWARE_ID_MASK 0x0f > #define HIDPP_SOFTWARE_ID_LEN 4 > > #define HIDPP20_FEAT_ROOT_IDX 0x00 > @@ -154,8 +157,8 @@ int uhidpp_debug = 1; > > /* Feature access report used by the HID++ 2.0 (and greater) protocol. */ > struct fap { > - uint8_t feature_index; > - uint8_t funcindex_clientid; > + uint8_t feature_idx; > + uint8_t funcidx_swid; > uint8_t params[HIDPP_REPORT_LONG_PARAMS_MAX]; > }; > > @@ -185,6 +188,8 @@ struct uhidpp_notification { > struct uhidpp_device { > uint8_t d_id; > uint8_t d_connected; > + uint8_t d_major; > + uint8_t d_minor; > struct { > struct ksensor b_sens[UHIDPP_NSENSORS]; > uint8_t b_feature_idx; > @@ -237,8 +242,10 @@ struct uhidpp_notification > *uhidpp_claim_notification(struct uhidpp_softc *); > int uhidpp_consume_notification(struct uhidpp_softc *, struct uhidpp_report > *); > int uhidpp_is_notification(struct uhidpp_softc *, struct uhidpp_report *); > > -int hidpp_get_protocol_version(struct uhidpp_softc *, uint8_t, int *, int > *); > +int hidpp_get_protocol_version(struct uhidpp_softc *, uint8_t, uint8_t *, > + uint8_t *); > > +int hidpp10_get_battery_status(struct uhidpp_softc *, uint8_t, uint8_t *); > int hidpp10_get_name(struct uhidpp_softc *, uint8_t, char *, size_t); > int hidpp10_get_serial(struct uhidpp_softc *, uint8_t, uint8_t *, size_t); > int hidpp10_get_type(struct uhidpp_softc *, uint8_t, const char **); > @@ -520,7 +527,7 @@ void > uhidpp_device_connect(struct uhidpp_softc *sc, struct uhidpp_device *dev) > { > struct ksensor *sens; > - int error, major, minor; > + int error; > uint8_t feature_type; > > MUTEX_ASSERT_LOCKED(&sc->sc_mtx); > @@ -529,30 +536,40 @@ uhidpp_device_connect(struct uhidpp_softc *sc, struct > uhidpp_device *dev) > if (dev->d_connected) > return; > > - error = hidpp_get_protocol_version(sc, dev->d_id, &major, &minor); > + error = hidpp_get_protocol_version(sc, dev->d_id, > + &dev->d_major, &dev->d_minor); > if (error) { > - DPRINTF("%s: protocol version failure: device_id=%d, > error=%d\n", > + DPRINTF("%s: protocol version failure: device_id=%d, " > + "error=%d\n", > __func__, dev->d_id, error); > return; > } > > DPRINTF("%s: device_id=%d, version=%d.%d\n", > - __func__, dev->d_id, major, minor); > + __func__, dev->d_id, dev->d_major, dev->d_minor); > > - error = hidpp20_root_get_feature(sc, dev->d_id, > - HIDPP20_FEAT_BATTERY_IDX, > - &dev->d_battery.b_feature_idx, &feature_type); > - if (error) { > - DPRINTF("%s: battery feature index failure: device_id=%d, " > - "error=%d\n", __func__, dev->d_id, error); > - return; > - } > + if (dev->d_major >= 2) { > + error = hidpp20_root_get_feature(sc, dev->d_id, > + HIDPP20_FEAT_BATTERY_IDX, > + &dev->d_battery.b_feature_idx, &feature_type); > + if (error) { > + DPRINTF("%s: battery feature index failure: " > + "device_id=%d, error=%d\n", > + __func__, dev->d_id, error); > + return; > + } > > - error = hidpp20_battery_get_capability(sc, dev->d_id, > - dev->d_battery.b_feature_idx, &dev->d_battery.b_nlevels); > - if (error) { > - DPRINTF("%s: battery capability failure: device_id=%d, " > - "error=%d\n", __func__, dev->d_id, error); > + error = hidpp20_battery_get_capability(sc, dev->d_id, > + dev->d_battery.b_feature_idx, &dev->d_battery.b_nlevels); > + if (error) { > + DPRINTF("%s: battery capability failure: device_id=%d, " > + "error=%d\n", __func__, dev->d_id, error); > + return; > + } > + > + } else if (dev->d_major == 1) { > + dev->d_battery.b_nlevels = HIDPP_BATTERY_NLEVELS; > + } else { > return; > } > > @@ -579,44 +596,58 @@ uhidpp_device_refresh(struct uhidpp_softc *sc, struct > uhidpp_device *dev) > > MUTEX_ASSERT_LOCKED(&sc->sc_mtx); > > - error = hidpp20_battery_get_level_status(sc, dev->d_id, > - dev->d_battery.b_feature_idx, > - &dev->d_battery.b_level, &dev->d_battery.b_next_level, > - &dev->d_battery.b_status); > - if (error) { > - DPRINTF("%s: battery level status failure: device_id=%d, " > - "error=%d\n", __func__, dev->d_id, error); > - return; > - } > + if (dev->d_major >= 2) { > + error = hidpp20_battery_get_level_status(sc, dev->d_id, > + dev->d_battery.b_feature_idx, > + &dev->d_battery.b_level, &dev->d_battery.b_next_level, > + &dev->d_battery.b_status); > + if (error) { > + DPRINTF("%s: battery status failure: device_id=%d, " > + "error=%d\n", > + __func__, dev->d_id, error); > + return; > + } > > - dev->d_battery.b_sens[0].value = dev->d_battery.b_level * 1000; > - dev->d_battery.b_sens[0].flags &= ~SENSOR_FUNKNOWN; > - if (dev->d_battery.b_nlevels < 10) { > - /* > - * According to the HID++ 2.0 specification, less than 10 levels > - * should be mapped to the following 4 levels: > - * > - * [0, 10] critical > - * [11, 30] low > - * [31, 80] good > - * [81, 100] full > - * > - * Since sensors are limited to 3 valid statuses, clamp it even > - * further. > - */ > - if (dev->d_battery.b_level <= 10) > - dev->d_battery.b_sens[0].status = SENSOR_S_CRIT; > - else if (dev->d_battery.b_level <= 30) > - dev->d_battery.b_sens[0].status = SENSOR_S_WARN; > - else > - dev->d_battery.b_sens[0].status = SENSOR_S_OK; > + dev->d_battery.b_sens[0].value = dev->d_battery.b_level * 1000; > + dev->d_battery.b_sens[0].flags &= ~SENSOR_FUNKNOWN; > + if (dev->d_battery.b_nlevels < 10) { > + /* > + * According to the HID++ 2.0 specification, less than > + * 10 levels should be mapped to the following 4 levels: > + * > + * [0, 10] critical > + * [11, 30] low > + * [31, 80] good > + * [81, 100] full > + * > + * Since sensors are limited to 3 valid statuses, clamp > + * it even further. > + */ > + if (dev->d_battery.b_level <= 10) > + dev->d_battery.b_sens[0].status = SENSOR_S_CRIT; > + else if (dev->d_battery.b_level <= 30) > + dev->d_battery.b_sens[0].status = SENSOR_S_WARN; > + else > + dev->d_battery.b_sens[0].status = SENSOR_S_OK; > + } else { > + /* > + * XXX the device supports battery mileage. The current > + * level must be checked against resp.fap.params[3] > + * given by hidpp20_battery_get_capability(). > + */ > + dev->d_battery.b_sens[0].status = SENSOR_S_UNKNOWN; > + } > } else { > - /* > - * XXX the device supports battery mileage. The current level > - * must be checked against resp.fap.params[3] given by > - * hidpp20_battery_get_capability(). > - */ > - dev->d_battery.b_sens[0].status = SENSOR_S_UNKNOWN; > + error = hidpp10_get_battery_status(sc, dev->d_id, > + &dev->d_battery.b_level); > + if (error) { > + DPRINTF("%s: battery status failure: device_id=%d, " > + "error=%d\n", > + __func__, dev->d_id, error); > + return; > + } > + dev->d_battery.b_sens[0].value = dev->d_battery.b_level * 1000; > + dev->d_battery.b_sens[0].flags &= ~SENSOR_FUNKNOWN; > } > } > > @@ -692,9 +723,9 @@ uhidpp_is_notification(struct uhidpp_softc *sc, struct > uhidpp_report *rep) > > /* An error must always be a response. */ > if ((rep->rap.sub_id == HIDPP_ERROR || > - rep->fap.feature_index == HIDPP20_ERROR) && > - rep->fap.funcindex_clientid == sc->sc_req->fap.feature_index && > - rep->fap.params[0] == sc->sc_req->fap.funcindex_clientid) > + rep->fap.feature_idx == HIDPP20_ERROR) && > + rep->fap.funcidx_swid == sc->sc_req->fap.feature_idx && > + rep->fap.params[0] == sc->sc_req->fap.funcidx_swid) > return 0; > > return 1; > @@ -702,7 +733,7 @@ uhidpp_is_notification(struct uhidpp_softc *sc, struct > uhidpp_report *rep) > > int > hidpp_get_protocol_version(struct uhidpp_softc *sc, uint8_t device_id, > - int *major, int *minor) > + uint8_t *major, uint8_t *minor) > { > struct uhidpp_report resp; > uint8_t params[3] = { 0, 0, HIDPP_FEAT_ROOT_PING_DATA }; > @@ -729,6 +760,37 @@ hidpp_get_protocol_version(struct uhidpp_softc *sc, > uint8_t device_id, > return 0; > } > > +int > +hidpp10_get_battery_status(struct uhidpp_softc *sc, uint8_t device_id, > + uint8_t *level) > +{ > + struct uhidpp_report resp; > + int error; > + > + error = hidpp_send_rap_report(sc, > + HIDPP_REPORT_ID_SHORT, > + device_id, > + HIDPP_GET_REGISTER, > + HIDPP_REG_BATTERY_STATUS, > + NULL, 0, &resp); > + DPRINTF("XXX %s: error=%d, device_id=%d\n", > + __func__, error, device_id); > + if (error) > + return error; > + if (resp.rap.params[0] < 1 || > + resp.rap.params[0] > HIDPP_BATTERY_NLEVELS) > + return -ERANGE; > + > + DPRINTF("XXX %s: p0=%x, p1=%x, p2=%x, device_id=%d\n", > + __func__, > + resp.rap.params[0], > + resp.rap.params[1], > + resp.rap.params[2], > + device_id); > + *level = (resp.rap.params[0] * 100) / HIDPP_BATTERY_NLEVELS; > + return 0; > +} > + > int > hidpp10_get_name(struct uhidpp_softc *sc, uint8_t device_id, > char *buf, size_t bufsiz) > @@ -848,7 +910,7 @@ hidpp10_enable_notifications(struct uhidpp_softc *sc, > uint8_t device_id) > > int > hidpp20_root_get_feature(struct uhidpp_softc *sc, uint8_t device_id, > - uint16_t feature, uint8_t *feature_index, uint8_t *feature_type) > + uint16_t feature, uint8_t *feature_idx, uint8_t *feature_type) > { > struct uhidpp_report resp; > uint8_t params[2] = { feature >> 8, feature & 0xff }; > @@ -866,14 +928,14 @@ hidpp20_root_get_feature(struct uhidpp_softc *sc, > uint8_t device_id, > if (resp.fap.params[0] == 0) > return -ENOENT; > > - *feature_index = resp.fap.params[0]; > + *feature_idx = resp.fap.params[0]; > *feature_type = resp.fap.params[1]; > return 0; > } > > int > hidpp20_battery_get_level_status(struct uhidpp_softc *sc, uint8_t device_id, > - uint8_t feature_index, uint8_t *level, uint8_t *next_level, uint8_t > *status) > + uint8_t feature_idx, uint8_t *level, uint8_t *next_level, uint8_t > *status) > { > struct uhidpp_report resp; > int error; > @@ -881,7 +943,7 @@ hidpp20_battery_get_level_status(struct uhidpp_softc *sc, > uint8_t device_id, > error = hidpp_send_fap_report(sc, > HIDPP_REPORT_ID_LONG, > device_id, > - feature_index, > + feature_idx, > HIDPP20_FEAT_BATTERY_LEVEL_FUNC, > NULL, 0, &resp); > if (error) > @@ -895,7 +957,7 @@ hidpp20_battery_get_level_status(struct uhidpp_softc *sc, > uint8_t device_id, > > int > hidpp20_battery_get_capability(struct uhidpp_softc *sc, uint8_t device_id, > - uint8_t feature_index, uint8_t *nlevels) > + uint8_t feature_idx, uint8_t *nlevels) > { > struct uhidpp_report resp; > int error; > @@ -903,7 +965,7 @@ hidpp20_battery_get_capability(struct uhidpp_softc *sc, > uint8_t device_id, > error = hidpp_send_fap_report(sc, > HIDPP_REPORT_ID_LONG, > device_id, > - feature_index, > + feature_idx, > HIDPP20_FEAT_BATTERY_CAPABILITY_FUNC, > NULL, 0, &resp); > if (error) > @@ -929,7 +991,7 @@ hidpp_send_validate(uint8_t report_id, int nparams) > > int > hidpp_send_fap_report(struct uhidpp_softc *sc, uint8_t report_id, > - uint8_t device_id, uint8_t feature_index, uint8_t funcindex_clientid, > + uint8_t device_id, uint8_t feature_idx, uint8_t funcidx_swid, > uint8_t *params, int nparams, struct uhidpp_report *resp) > { > struct uhidpp_report req; > @@ -941,9 +1003,9 @@ hidpp_send_fap_report(struct uhidpp_softc *sc, uint8_t > report_id, > > memset(&req, 0, sizeof(req)); > req.device_id = device_id; > - req.fap.feature_index = feature_index; > - req.fap.funcindex_clientid = > - (funcindex_clientid << HIDPP_SOFTWARE_ID_LEN) | HIDPP_SOFTWARE_ID; > + req.fap.feature_idx = feature_idx; > + req.fap.funcidx_swid = > + (funcidx_swid << HIDPP_SOFTWARE_ID_LEN) | HIDPP_SOFTWARE_ID; > memcpy(req.fap.params, params, nparams); > return hidpp_send_report(sc, report_id, &req, resp); > } > @@ -1024,7 +1086,7 @@ hidpp_send_report(struct uhidpp_softc *sc, uint8_t > report_id, > resp->rap.sub_id == HIDPP_ERROR) > error = resp->rap.params[1]; > else if (sc->sc_resp_state == HIDPP_REPORT_ID_LONG && > - resp->fap.feature_index == HIDPP20_ERROR) > + resp->fap.feature_idx == HIDPP20_ERROR) > error = resp->fap.params[1]; > > out: Regards, Anindya