On Fri, February 14, 2014 17:07, Andre de Oliveira wrote:
> hello.
>
> blambert@ suggested me to write a driver for exposing usb-based
> uninterruptable power systems devices data as sysctl(8) sensors, thus
> enabling people to write "shutdown policies" using sensorsd(8), which
> can replaces apcupsd in some cases.
>
> I received some feedback from reyk@ and blambert@, hope it's now ok for
> tech@ comments.
>
> -a
Hi.
Tested with upd0 at uhub2 port 1 "American Power Conversion Back-UPS RS 500
FW:30.j5.I USB FW:j5" rev 1.10/0.06 addr 2
kirby@humppalaki:ttyp0<kirby> % sysctl hw.sensors.upd0
hw.sensors.upd0.volt0=1.20 VDC (battery nominal volt)
hw.sensors.upd0.volt1=0.00 VDC (battery current volt)
hw.sensors.upd0.indicator0=Off (battery charging)
hw.sensors.upd0.indicator1=Off (battery discharging)
hw.sensors.upd0.indicator2=On (battery present)
hw.sensors.upd0.indicator3=Off (shutdown imminent)
hw.sensors.upd0.indicator4=On (acpower present)
hw.sensors.upd0.percent0=100.00% (battery load)

Currently the problem is when UPS is attached as /dev/updX, apcupsd stops
working. So shpuld /dev/upd be enabled by default?
And another moment. What is about MODBUS? Are you going to support other APC
protocols? I'm monitoring apcupsd mailing lists and it doesn't look like APC
is giving all the documentation for developers on demand.
As it looks to me, this driver is going to have half of apcupsd usb devices
support to be really useful.
But SNMP support would be nice.
Just my thoughts...

>
> diff --git a/.gitignore b/.gitignore
> new file mode 100644
> index 0000000..a43f9f5
> --- /dev/null
> +++ b/.gitignore
> @@ -0,0 +1 @@
> +**.swp
> diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
> index beaffb8..76b20e7 100644
> --- a/share/man/man4/Makefile
> +++ b/share/man/man4/Makefile
> @@ -61,7 +61,7 @@ MAN=        aac.4 ac97.4 acphy.4 \
>       uk.4 ukbd.4 \
>       ukphy.4 ulpt.4 umass.4 umbg.4 umct.4 umidi.4 umodem.4 ums.4 umsm.4 \
>       unix.4 uow.4 uoaklux.4 uoakrh.4 uoakv.4 \
> -     upgt.4 upl.4 uplcom.4 ural.4 urio.4 url.4 urlphy.4 \
> +     upd.4 upgt.4 upl.4 uplcom.4 ural.4 urio.4 url.4 urlphy.4 \
>       urndis.4 urtw.4 urtwn.4 usb.4  usbf.4 uslcom.4 usps.4 \
>       uthum.4 uticom.4 utpms.4 utwitch.4 utrh.4 uts.4 uvideo.4 uvisor.4 \
>       uvscom.4 uyap.4 \
> diff --git a/share/man/man4/upd.4 b/share/man/man4/upd.4
> new file mode 100644
> index 0000000..5a9054d
> --- /dev/null
> +++ b/share/man/man4/upd.4
> @@ -0,0 +1,96 @@
> +.\"  $OpenBSD$
> +.\"
> +.\" Copyright (c) 2014 Andre de Oliveira <deoliveira...@googlemail.com>
> +.\"
> +.\" Permission to use, copy, modify, and distribute this software for any
> +.\" purpose with or without fee is hereby granted, provided that the above
> +.\" copyright notice and this permission notice appear in all copies.
> +.\"
> +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> +.\"
> +.Dd $Mdocdate: February 8 2014 $
> +.Dt UPD 4
> +.Os
> +.Sh NAME
> +.Nm upd
> +.Nd USB Power Devices battery voltage and load sensor
> +.Sh SYNOPSIS
> +.Cd "upd* at uhub?"
> +.Sh DESCRIPTION
> +The
> +.Nm
> +exposes data from USB Power Devices (such as an UPS), as hardware sensors
> +via
> +.Xr sysctl 3 .
> +The following devices are supported by the
> +.Nm
> +driver:
> +.Bl -column
> +.Pp
> +.It Li "American Power Conversion Smart-UPS 750"
> +.It Li "American Power Conversion Back-UPS CS 350"
> +.El
> +.Pp
> +The following sensors are provided by the
> +.Nm
> +driver, which can be monitored using
> +.Xr sensorsd 8 :
> +.Bl -column
> +.Pp
> +.It Battery Nominal Voltage
> +.It Battery Current Voltage
> +.It Battery Charging
> +.It Battery Discharging
> +.It Battery Present
> +.It Shutdown Imminent
> +.It AC Power Present
> +.It Battery Current Load
> +.El
> +.Sh EXAMPLES
> +In this example, the upd0 device is a regular UPS.
> +We use an entry on
> +.Xr sensorsd 8
> +to take an action when the battery level is below a 70%:
> +.Pp
> +.Bd -literal -offset indent
> +hw.sensors.upd0.percent0:low=70:command=/etc/sensorsd/lowbattwarn %l
> +.Ed
> +.Pp
> +The contents of lowbattwarn could be:
> +.Pp
> +.Bd -literal -offset indent
> +#!/bin/ksh
> +
> +if [ $# -lt 1 ]; then
> +        return;
> +fi
> +
> +if [ $1 -lt 70 ]; then
> +        logger "ups battery warning-level, halting"
> +        /sbin/halt -p
> +fi
> +.Ed
> +.Sh SEE ALSO
> +.Xr intro 4 ,
> +.Xr uhub 4 ,
> +.Xr sensorsd 8 ,
> +.Xr sysctl 8
> +.Sh HISTORY
> +The
> +.Nm
> +driver first appeared in .Ox
> +.Sh AUTHORS
> +The
> +.Nm
> +driver was written by Andre de Oliveira <deoliveira...@googlemail.com>,
> +sponsored by Esdenera Networks GmbH.
> +.Sh BUGS
> +When the battery is not present even with Battery Presence indicator set to
> Off
> +the remaining battery sensors will still be present, besides their values can
> +not be trusted.
> diff --git a/share/man/man4/usb.4 b/share/man/man4/usb.4
> index 9009e62..f631fe2 100644
> --- a/share/man/man4/usb.4
> +++ b/share/man/man4/usb.4
> @@ -281,6 +281,8 @@ Maxim/Dallas DS2490 USB 1-Wire adapter
>  Prolific based host-to-host adapters
>  .It Xr usps 4
>  USPS composite AC power and temperature sensor
> +.It Xr upd 4
> +USB Power Devices battery voltage and load sensor
>  .It Xr uts 4
>  USB touchscreen support
>  .It Xr uyap 4
> diff --git a/sys/arch/.gitignore b/sys/arch/.gitignore
> new file mode 100644
> index 0000000..af7465e
> --- /dev/null
> +++ b/sys/arch/.gitignore
> @@ -0,0 +1 @@
> +*/compile
> diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC
> index 0a1bf36..77225c2 100644
> --- a/sys/arch/amd64/conf/GENERIC
> +++ b/sys/arch/amd64/conf/GENERIC
> @@ -236,6 +236,7 @@ udsbr*    at uhub?                # D-Link DSB-R100 radio
>  radio*       at udsbr?               # USB radio
>  uberry*      at uhub?                # Research In Motion Blackberry
>  ugen*        at uhub?                # USB Generic driver
> +upd* at uhub?                # USB Power Devices sensors
>  uath*        at uhub?                # Atheros AR5005UG/AR5005UX
>  ural*        at uhub?                # Ralink RT2500USB
>  rum* at uhub?                # Ralink RT2501USB/RT2601USB
> diff --git a/sys/dev/usb/files.usb b/sys/dev/usb/files.usb
> index 9ad82c5..42592f7 100644
> --- a/sys/dev/usb/files.usb
> +++ b/sys/dev/usb/files.usb
> @@ -60,6 +60,10 @@ device     ugen
>  attach       ugen at uhub
>  file dev/usb/ugen.c                  ugen                    needs-flag
>
> +# USB Power Devices
> +device upd
> +attach upd at uhub
> +file   dev/usb/upd.c                 upd
>
>  # HID
>  # HID "bus"
> diff --git a/sys/dev/usb/upd.c b/sys/dev/usb/upd.c
> new file mode 100644
> index 0000000..5a770b9
> --- /dev/null
> +++ b/sys/dev/usb/upd.c
> @@ -0,0 +1,413 @@
> +/*   $OpenBSD$ */
> +
> +/*
> + * Copyright (c) 2014 Andre de Oliveira <deoliveira...@googlemail.com>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +/* Driver for USB Power Devices sensors */
> +
> +#include <sys/param.h>
> +#include <sys/systm.h>
> +#include <sys/kernel.h>
> +#include <sys/malloc.h>
> +#include <sys/device.h>
> +#include <sys/sensors.h>
> +
> +#include <dev/usb/usb.h>
> +#include <dev/usb/usbdi.h>
> +#include <dev/usb/usbdevs.h>
> +#include <dev/usb/usbhid.h>
> +#include <dev/usb/hid.h>
> +
> +#ifdef USB_DEBUG
> +#define UPD_DEBUG
> +#endif
> +
> +#ifdef UPD_DEBUG
> +int upddebug = 9;
> +#define DPRINTF(x)   do { if (upddebug) printf x; } while (0)
> +#define DPRINTFN(n, x)       do { if (upddebug >= (n)) printf x; } while (0)
> +#else
> +#define DPRINTF(x)
> +#define DPRINTFN(n, x)
> +#endif
> +
> +#define UPD_USB_TMOUT                1000
> +
> +/* protocol */
> +#define UPD_CMD_GET_BATTNOMV 0x0a
> +#define UPD_CMD_GET_BATTCURV 0x0b
> +#define UPD_CMD_GET_BATTLOAD 0x0c
> +#define UPD_CMD_GET_UPSMISC  0x07 /* misc flags from ups */
> +
> +#define UPD_CMD_NUM          4
> +
> +enum upd_sensor_id {
> +     UPD_SENSOR_UNKNOWN,
> +     UPD_SENSOR_BATTNOMV,
> +     UPD_SENSOR_BATTCURV,
> +     UPD_SENSOR_BATTLOAD,
> +     UPD_SENSOR_BATTCHARGING,
> +     UPD_SENSOR_BATTDISCHARG,
> +     UPD_SENSOR_BATTPRESENT,
> +     UPD_SENSOR_SHUTIMMINENT,
> +     UPD_SENSOR_ACPOWER,
> +     UPD_SENSOR_ACOFFTIME,
> +     UPD_SENSOR_NUM
> +};
> +
> +struct upd_report_param {
> +     int                      enabled;
> +     u_int8_t                 cmd;           /* usage id (issue command) */
> +     char                    *type_s;        /* sensor string */
> +     struct hid_location      loc;           /* size, count, pos */
> +};
> +
> +static struct upd_report_param upd_report_params[UPD_SENSOR_NUM] = {
> +     { 0, 0x0,                  "unknown",              { 0, 0, 0 } },
> +     { 1, UPD_CMD_GET_BATTNOMV, "battery nominal volt", { 0x10, 0x0, 0x0 } },
> +     { 1, UPD_CMD_GET_BATTCURV, "battery current volt", { 0x10, 0x0, 0x0 } },
> +     { 1, UPD_CMD_GET_BATTLOAD, "battery load",         { 0x08, 0x0, 0x0 } },
> +     { 1, UPD_CMD_GET_UPSMISC,  "battery charging",     { 0x01, 0x0, 0x0 } },
> +     { 1, UPD_CMD_GET_UPSMISC,  "battery discharging",  { 0x01, 0x0, 0x01 } 
> },
> +     { 1, UPD_CMD_GET_UPSMISC,  "battery present",      { 0x01, 0x0, 0x03 } 
> },
> +     { 1, UPD_CMD_GET_UPSMISC,  "shutdown imminent",    { 0x01, 0x0, 0x06 } 
> },
> +     { 1, UPD_CMD_GET_UPSMISC,  "acpower present",      { 0x0, 0x0, 0x0 } },
> +     { 0, UPD_CMD_GET_UPSMISC,  "acpower off time",     { 0x0, 0x0, 0x0 } }
> +};
> +
> +struct upd_udata {
> +     u_int8_t        cmd;
> +     u_int16_t       dlen;
> +     enum hid_kind   hkind;
> +     u_int8_t        data[8];
> +     int             rfail;
> +};
> +
> +struct upd_sensor {
> +     struct ksensor sensor;
> +     enum upd_sensor_id id;
> +     int attached;
> +};
> +
> +struct upd_softc {
> +     struct device            sc_hdev;
> +     struct usbd_device      *sc_udev;
> +     int                      sc_num_sensors;
> +
> +     /* sensor framework */
> +     struct upd_sensor        sc_sensor[UPD_SENSOR_NUM];
> +     struct upd_udata         sc_usbdata[UPD_CMD_NUM];
> +     struct ksensordev        sc_sensordev;
> +     struct sensor_task      *sc_sensortask;
> +};
> +
> +struct upd_type {
> +     struct usb_devno        upd_dev;
> +     u_int16_t               upd_flags;
> +};
> +
> +static const struct upd_type upd_devs[] = {
> +     { { USB_VENDOR_APC, USB_PRODUCT_APC_UPS }, 0 },
> +     { { USB_VENDOR_APC, USB_PRODUCT_APC_UPS5G }, 0 },
> +};
> +#define upd_lookup(v, p)  \
> +     ((const struct upd_type *)usb_lookup(upd_devs, v, p))
> +
> +int  upd_match(struct device *, void *, void *);
> +void upd_attach(struct device *, struct device *, void *);
> +int  upd_detach(struct device *, int);
> +
> +void upd_setup_sensors(struct upd_softc *);
> +void upd_refresh(void *);
> +void upd_refresh_data(struct upd_softc *);
> +int  upd_read_data(struct upd_softc *, struct upd_udata *, int);
> +struct upd_udata * upd_usbdata_lookup(struct upd_udata *, u_int8_t);
> +
> +struct cfdriver upd_cd = {
> +     NULL, "upd", DV_DULL
> +};
> +
> +const struct cfattach upd_ca = {
> +     sizeof(struct upd_softc),
> +     upd_match,
> +     upd_attach,
> +     upd_detach
> +};
> +
> +int
> +upd_match(struct device *parent, void *match, void *aux)
> +{
> +     struct usb_attach_arg *uaa = aux;
> +
> +     if (upd_lookup(uaa->vendor, uaa->product) == NULL)
> +                return (UMATCH_NONE);
> +
> +     DPRINTFN(3, ("upd: vendor=0x%x, product=0x%x\n", uaa->vendor,
> +         uaa->product));
> +
> +     return (UMATCH_VENDOR_PRODUCT);
> +}
> +
> +void
> +upd_attach(struct device *parent, struct device *self, void *aux)
> +{
> +     struct upd_softc *sc = (struct upd_softc *)self;
> +     struct usb_attach_arg *uaa = (struct usb_attach_arg *)aux;
> +     struct usbd_device *udev;
> +     int i;
> +
> +     sc->sc_udev = udev = uaa->device;
> +     sc->sc_num_sensors = 0;
> +
> +     strlcpy(sc->sc_sensordev.xname, sc->sc_hdev.dv_xname,
> +         sizeof(sc->sc_sensordev.xname));
> +     upd_setup_sensors(sc);
> +
> +     /* attach sensors */
> +     for (i = 0; i < UPD_SENSOR_NUM; i++) {
> +             if (sc->sc_sensor[i].id == UPD_SENSOR_UNKNOWN)
> +                     continue;
> +             sc->sc_sensor[i].sensor.flags |= SENSOR_FINVALID;
> +             sc->sc_sensor[i].sensor.value = 0;
> +             sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i].sensor);
> +             sc->sc_sensor[i].attached = 1;
> +             sc->sc_num_sensors++;
> +     }
> +
> +     DPRINTFN(3, ("upd: sc_num_sensors=%d\n", sc->sc_num_sensors));
> +
> +     if (sc->sc_num_sensors > 0) {
> +             sc->sc_sensortask = sensor_task_register(sc, upd_refresh, 6);
> +             if (sc->sc_sensortask == NULL) {
> +                     printf(", unable to register update task\n");
> +                     return;
> +             }
> +             sensordev_install(&sc->sc_sensordev);
> +     }
> +
> +     /*
> +      * init usbdata
> +      * those commands width were identified from observing apcupsd/ugen(4)
> +      * data exchange
> +      */
> +     sc->sc_usbdata[0].cmd = UPD_CMD_GET_BATTNOMV;
> +     sc->sc_usbdata[0].dlen = 0x03;
> +     sc->sc_usbdata[0].hkind = hid_feature;
> +     sc->sc_usbdata[1].cmd = UPD_CMD_GET_BATTCURV;
> +     sc->sc_usbdata[1].dlen = 0x02;
> +     sc->sc_usbdata[1].hkind = hid_feature;
> +     sc->sc_usbdata[2].cmd = UPD_CMD_GET_BATTLOAD;
> +     sc->sc_usbdata[2].dlen = 0x03;
> +     sc->sc_usbdata[2].hkind = hid_feature;
> +     sc->sc_usbdata[3].cmd = UPD_CMD_GET_UPSMISC;
> +     sc->sc_usbdata[3].dlen = 0x03;
> +     sc->sc_usbdata[3].hkind = hid_feature;
> +
> +     DPRINTFN(3, ("upd_attach: complete\n"));
> +}
> +
> +int
> +upd_detach(struct device *self, int flags)
> +{
> +     struct upd_softc *sc = (struct upd_softc *)self;
> +     int i;
> +
> +     if (sc->sc_num_sensors > 0) {
> +             wakeup(&sc->sc_sensortask);
> +             sensordev_deinstall(&sc->sc_sensordev);
> +             for (i = 0; i < UPD_SENSOR_NUM; i++) {
> +                     if (sc->sc_sensor[i].attached) {
> +                             sensor_detach(&sc->sc_sensordev,
> +                                     &sc->sc_sensor[i].sensor);
> +                             DPRINTFN(5, ("upd_detach: %s\n",
> +                                 sc->sc_sensor[i].sensor.desc));
> +                     }
> +             }
> +             if (sc->sc_sensortask != NULL)
> +                     sensor_task_unregister(sc->sc_sensortask);
> +     }
> +
> +     DPRINTFN(3, ("upd_detach: complete\n"));
> +     return (0);
> +}
> +
> +int
> +upd_read_data(struct upd_softc *sc, struct upd_udata *udata, int tmout)
> +{
> +     usb_device_request_t req;
> +     int ucr_actlen = 0;
> +     int err = 0;
> +     enum hid_kind hkind;
> +     size_t buflen;
> +     u_int16_t dlen;
> +     u_int8_t cmd, *buf = NULL;
> +     void *ptr = NULL;
> +
> +     buf = udata->data;
> +     cmd = udata->cmd;
> +     dlen = udata->dlen;
> +     hkind = udata->hkind;
> +     buflen = sizeof(buf);
> +
> +     if (buf == NULL || buflen == 0)
> +             return (0);
> +
> +     ptr = malloc(buflen, M_TEMP, M_WAITOK);
> +
> +     req.bmRequestType = UT_READ_CLASS_INTERFACE;
> +     req.bRequest = UR_GET_REPORT;
> +
> +     USETW(req.wValue, ((hkind + 1) << 8) | cmd);
> +     USETW(req.wIndex, 0);
> +     USETW(req.wLength, dlen);
> +
> +     err = usbd_do_request_flags(sc->sc_udev, &req, ptr, USBD_SHORT_XFER_OK,
> +         &ucr_actlen, tmout);
> +
> +     if (err)
> +             goto ret;
> +
> +     memcpy(buf, ptr, buflen);
> +
> +     DPRINTFN(5, ("actlen=%02x ptr[0]=%02x ptr[1]=%02x ptr[2]=%02x\n",
> +         ucr_actlen, ((u_int8_t *)ptr)[0], ((u_int8_t *)ptr)[1],
> +         ((u_int8_t *)ptr)[2]));
> +
> +ret:
> +     if (ptr)
> +             free(ptr, M_TEMP);
> +
> +     return (err);
> +}
> +
> +void
> +upd_setup_sensors(struct upd_softc *sc)
> +{
> +     int i;
> +
> +     for (i = 0; i < UPD_SENSOR_NUM; i++) {
> +             if (upd_report_params[i].enabled != 1)
> +                     continue;
> +
> +             sc->sc_sensor[i].id = i;
> +             strlcpy(sc->sc_sensor[i].sensor.desc,
> +                 upd_report_params[i].type_s,
> +                 sizeof(sc->sc_sensor[i].sensor.desc));
> +             sc->sc_sensor[i].attached = 0;
> +
> +             switch (i) {
> +             case UPD_SENSOR_BATTNOMV:
> +             case UPD_SENSOR_BATTCURV:
> +                     sc->sc_sensor[i].sensor.type = SENSOR_VOLTS_DC;
> +                     break;
> +             case UPD_SENSOR_BATTLOAD:
> +                     sc->sc_sensor[i].sensor.type = SENSOR_PERCENT;
> +                     break;
> +             case UPD_SENSOR_SHUTIMMINENT:
> +             case UPD_SENSOR_BATTCHARGING:
> +             case UPD_SENSOR_BATTDISCHARG:
> +             case UPD_SENSOR_BATTPRESENT:
> +             case UPD_SENSOR_ACPOWER:
> +                     sc->sc_sensor[i].sensor.type = SENSOR_INDICATOR;
> +                     break;
> +             }
> +     }
> +}
> +
> +void
> +upd_refresh(void *arg)
> +{
> +     struct upd_softc *sc = (struct upd_softc *)arg;
> +     struct hid_location *loc;
> +     struct upd_udata *udata;
> +     u_long hdata;
> +     u_int8_t cmd;
> +     u_int8_t *buf;
> +     int i;
> +
> +     upd_refresh_data(sc);
> +
> +     for (i = 0; i < UPD_SENSOR_NUM; i++) {
> +             if (sc->sc_sensor[i].attached != 1 ||
> +                 upd_report_params[i].enabled != 1)
> +                     continue;
> +
> +             cmd = upd_report_params[i].cmd;
> +             udata = upd_usbdata_lookup(sc->sc_usbdata, cmd);
> +
> +             /* skip on eventual read failures or unsupported features */
> +             if (udata->rfail)
> +                     continue;
> +
> +             buf = udata->data;
> +             loc = &upd_report_params[i].loc;
> +             hdata = hid_get_data(buf + 1, loc);
> +
> +             switch (i) {
> +             case UPD_SENSOR_BATTNOMV:
> +             case UPD_SENSOR_BATTCURV:
> +             case UPD_SENSOR_BATTLOAD:
> +                     if (sc->sc_sensor[UPD_SENSOR_BATTPRESENT].sensor.value)
> +                             hdata *= 1000; /* scale adjust */
> +                     else
> +                             hdata = 0;
> +                     break;
> +             case UPD_SENSOR_ACPOWER:
> +                     /* use discharging flag as acpower indicator */
> +                     if (sc->sc_sensor[UPD_SENSOR_BATTDISCHARG].sensor.value)
> +                             hdata = 0;
> +                     else
> +                             hdata = 1;
> +                     break;
> +             }
> +
> +             sc->sc_sensor[i].sensor.flags &= ~SENSOR_FINVALID;
> +             sc->sc_sensor[i].sensor.value = hdata;
> +             DPRINTFN(3, ("%s: %s: hidget data: %d\n",
> +                          sc->sc_sensordev.xname,
> +                          upd_report_params[i].type_s, hdata));
> +     }
> +}
> +
> +void
> +upd_refresh_data(struct upd_softc *sc)
> +{
> +     struct upd_udata *udata;
> +     int i, ret;
> +
> +     for (i = 0; i < UPD_CMD_NUM; i++) {
> +             udata = &sc->sc_usbdata[i];
> +             bzero(udata->data, sizeof(udata->data));
> +             ret = upd_read_data(sc, udata, UPD_USB_TMOUT);
> +             if (ret != USBD_NORMAL_COMPLETION) {
> +                     DPRINTFN(5, ("upd: data read fail\n"));
> +                     udata->rfail = 1;
> +             }
> +             udata->rfail = 0;
> +     }
> +}
> +
> +struct upd_udata *
> +upd_usbdata_lookup(struct upd_udata *usbdata, u_int8_t cmd)
> +{
> +     int i;
> +
> +     for (i = 0; i < UPD_CMD_NUM; i++)
> +             if (usbdata[i].cmd == cmd)
> +                     return (&usbdata[i]);
> +
> +     return (NULL);
> +}
>
>


Reply via email to