LCOV - code coverage report
Current view: top level - dev/usb - uoak_subr.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 175 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 18 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: uoak_subr.c,v 1.9 2018/05/01 18:14:46 landry Exp $   */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2012 Yojiro UO <yuo@nui.org>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : /* TORADEX OAK seriese sensors: common functions */ 
      20             : /* http://developer.toradex.com/files/toradex-dev/uploads/media/Oak/Oak_ProgrammingGuide.pdf */
      21             : 
      22             : #include <sys/param.h>
      23             : #include <sys/systm.h>
      24             : #include <sys/kernel.h>
      25             : #include <sys/device.h>
      26             : #include <sys/conf.h>
      27             : #include <sys/sensors.h>
      28             : 
      29             : #include <dev/usb/usb.h>
      30             : #include <dev/usb/usbhid.h>
      31             : #include <dev/usb/usbdi.h>
      32             : #include <dev/usb/usbdi_util.h>
      33             : #include <dev/usb/usbdevs.h>
      34             : #include <dev/usb/uhidev.h>
      35             : #include "uoak.h"
      36             : 
      37             : #define UOAK_RETRY_DELAY         100 /* 100ms, XXX too long? */
      38             : #define UOAK_RESPONSE_DELAY      10  /* 10ms,  XXX too short? */
      39             : /*
      40             :  *  basic procedure to issue command to the OAK device.
      41             :  *  1) check the device is ready to accept command.
      42             :  *     if a report of a FEATURE_REPORT request is not start 0xff,
      43             :  *     wait for a while, and retry till the reponse start with 0xff.
      44             :  *  2) issue command.  (set or get)
      45             :  *  3) if the command will response, wait for a while, and issue
      46             :  *     FEATURE_REPORT. leading 0xff indicate the response is valid.
      47             :  *     if the first byte is not 0xff, retry.
      48             :  */
      49             : int
      50           0 : uoak_check_device_ready(struct uoak_softc *sc)
      51             : {
      52             :         int actlen;
      53             : 
      54           0 :         actlen = uhidev_get_report(sc->sc_hdev->sc_parent, UHID_FEATURE_REPORT,
      55           0 :             sc->sc_hdev->sc_report_id, &sc->sc_buf, sc->sc_flen);
      56           0 :         if (actlen != sc->sc_flen)
      57           0 :                 return EIO;
      58             : 
      59           0 :         if (sc->sc_buf[0] != 0xff)
      60           0 :                 return -1;
      61             : 
      62           0 :         return 0;
      63           0 : }
      64             : 
      65             : int
      66           0 : uoak_set_cmd(struct uoak_softc *sc)
      67             : {
      68             :         int actlen;
      69           0 :         sc->sc_rcmd.dir = OAK_SET;
      70             : 
      71           0 :         while (uoak_check_device_ready(sc) < 0)
      72           0 :                 usbd_delay_ms(sc->sc_udev, UOAK_RETRY_DELAY);
      73             : 
      74           0 :         actlen = uhidev_set_report(sc->sc_hdev->sc_parent, UHID_FEATURE_REPORT,
      75           0 :             sc->sc_hdev->sc_report_id, &sc->sc_rcmd, sc->sc_flen);
      76           0 :         if (actlen != sc->sc_flen)
      77           0 :                 return EIO;
      78             : 
      79           0 :         return 0;
      80           0 : }
      81             : 
      82             : int
      83           0 : uoak_get_cmd(struct uoak_softc *sc)
      84             : {
      85             :         int actlen;
      86           0 :         sc->sc_rcmd.dir = OAK_GET;
      87             : 
      88             :         /* check the device is ready to request */
      89           0 :         while (uoak_check_device_ready(sc) < 0) 
      90           0 :                 usbd_delay_ms(sc->sc_udev, UOAK_RETRY_DELAY);
      91             : 
      92             :         /* issue request */
      93           0 :         actlen = uhidev_set_report(sc->sc_hdev->sc_parent, UHID_FEATURE_REPORT,
      94           0 :             sc->sc_hdev->sc_report_id, &sc->sc_rcmd, sc->sc_flen);
      95           0 :         if (actlen != sc->sc_flen)
      96           0 :                 return EIO;
      97             : 
      98             :         /* wait till the device ready to return the request */
      99           0 :         while (uoak_check_device_ready(sc) < 0) 
     100           0 :                 usbd_delay_ms(sc->sc_udev, UOAK_RESPONSE_DELAY); 
     101             : 
     102           0 :         return 0;
     103           0 : }
     104             : 
     105             : /*
     106             :  * Functions to access device configurations.
     107             :  * OAK sensor have some storages to store its configuration.
     108             :  * (RAM, FLASH and others)
     109             :  */
     110             : int
     111           0 : uoak_get_device_name(struct uoak_softc *sc, enum uoak_target target)
     112             : {
     113           0 :         memset(&sc->sc_rcmd, 0, sizeof(struct uoak_rcmd));
     114           0 :         sc->sc_rcmd.target = target;
     115           0 :         sc->sc_rcmd.datasize = 0x15;
     116           0 :         USETW(&sc->sc_rcmd.cmd, OAK_CMD_DEVNAME);
     117             : 
     118           0 :         if (uoak_get_cmd(sc) < 0)
     119           0 :                 return EIO;
     120             : 
     121           0 :         strlcpy(sc->sc_config[target].devname, sc->sc_buf+1, 
     122             :             sizeof(sc->sc_config[target].devname));
     123           0 :         return 0;
     124           0 : }
     125             : 
     126             : int
     127           0 : uoak_get_report_mode(struct uoak_softc *sc, enum uoak_target target)
     128             : {
     129           0 :         memset(&sc->sc_rcmd, 0, sizeof(struct uoak_rcmd));
     130           0 :         sc->sc_rcmd.target = target;
     131           0 :         sc->sc_rcmd.datasize = 0x1;
     132           0 :         USETW(&sc->sc_rcmd.cmd, OAK_CMD_REPORTMODE);
     133             : 
     134           0 :         if (uoak_get_cmd(sc) < 0)
     135           0 :                 return EIO;
     136             : 
     137           0 :         sc->sc_config[target].report_mode = sc->sc_buf[1];
     138           0 :         return 0;
     139           0 : }
     140             : 
     141             : int
     142           0 : uoak_get_report_rate(struct uoak_softc *sc, enum uoak_target target)
     143             : {
     144             :         uint16_t result;
     145           0 :         memset(&sc->sc_rcmd, 0, sizeof(struct uoak_rcmd));
     146           0 :         sc->sc_rcmd.target = target;
     147           0 :         sc->sc_rcmd.datasize = 0x2;
     148           0 :         USETW(&sc->sc_rcmd.cmd, OAK_CMD_REPORTRATE);
     149             : 
     150           0 :         if (uoak_get_cmd(sc) < 0)
     151           0 :                 return EIO;
     152             : 
     153           0 :         result = (sc->sc_buf[2] << 8) + sc->sc_buf[1];
     154           0 :         sc->sc_config[target].report_rate = result;
     155             : 
     156           0 :         return 0;
     157           0 : }
     158             : 
     159             : int
     160           0 : uoak_get_sample_rate(struct uoak_softc *sc, enum uoak_target target)
     161             : {
     162             :         uint16_t result;
     163           0 :         memset(&sc->sc_rcmd, 0, sizeof(struct uoak_rcmd));
     164           0 :         sc->sc_rcmd.target = target;
     165           0 :         sc->sc_rcmd.datasize = 0x2;
     166           0 :         USETW(&sc->sc_rcmd.cmd, OAK_CMD_SAMPLERATE);
     167             : 
     168           0 :         if (uoak_get_cmd(sc) < 0)
     169           0 :                 return EIO;
     170             : 
     171           0 :         result = (sc->sc_buf[2] << 8) + sc->sc_buf[1];
     172           0 :         sc->sc_config[target].sample_rate = result;
     173             : 
     174           0 :         return 0;
     175           0 : }
     176             : 
     177             : int
     178           0 : uoak_set_sample_rate(struct uoak_softc *sc, enum uoak_target target, int rate)
     179             : {
     180           0 :         memset(&sc->sc_rcmd, 0, sizeof(struct uoak_rcmd));
     181           0 :         sc->sc_rcmd.target = target;
     182           0 :         sc->sc_rcmd.datasize = 0x2;
     183           0 :         USETW(&sc->sc_rcmd.cmd, OAK_CMD_SAMPLERATE);
     184             : 
     185             : #if 0
     186             :         sc->sc_rcmd.val[0] = (uint8_t)(rate & 0xff);
     187             :         sc->sc_rcmd.val[1] = (uint8_t)((rate >> 8) & 0xff)
     188             : #else
     189           0 :         USETW(sc->sc_rcmd.val, rate);
     190             : #endif
     191             : 
     192           0 :         if (uoak_set_cmd(sc) < 0)
     193           0 :                 return EIO;
     194             : 
     195           0 :         return 0;
     196           0 : }
     197             : 
     198             : /*
     199             :  * LED I/O
     200             :  */
     201             : int
     202           0 : uoak_led_status(struct uoak_softc *sc, enum uoak_target target, uint8_t *mode)
     203             : {
     204           0 :         memset(&sc->sc_rcmd, 0, sizeof(struct uoak_rcmd));
     205           0 :         sc->sc_rcmd.target = target;
     206           0 :         sc->sc_rcmd.datasize = 0x1;
     207           0 :         USETW(&sc->sc_rcmd.cmd, OAK_CMD_LEDMODE);
     208             : 
     209           0 :         if (uoak_get_cmd(sc) < 0)
     210           0 :                 return EIO;
     211             : 
     212           0 :         *mode =  sc->sc_buf[1];
     213           0 :         return 0;
     214           0 : }
     215             : 
     216             : int
     217           0 : uoak_led_ctrl(struct uoak_softc *sc, enum uoak_target target, uint8_t mode)
     218             : {
     219           0 :         memset(&sc->sc_rcmd, 0, sizeof(struct uoak_rcmd));
     220             : 
     221           0 :         sc->sc_rcmd.target = target;
     222           0 :         sc->sc_rcmd.datasize = 0x1;
     223           0 :         USETW(&sc->sc_rcmd.cmd, OAK_CMD_LEDMODE);
     224           0 :         sc->sc_rcmd.val[0] = mode;
     225             : 
     226           0 :         return uoak_set_cmd(sc);
     227             : }
     228             : 
     229             : /* device setting: query and pretty print */
     230             : void
     231           0 : uoak_get_devinfo(struct uoak_softc *sc)
     232             : {
     233             :         /* get device serial# */
     234           0 :         usbd_fill_deviceinfo(sc->sc_udev, &sc->sc_udi);
     235           0 : }
     236             : 
     237             : void
     238           0 : uoak_get_setting(struct uoak_softc *sc, enum uoak_target target)
     239             : {
     240             :         /* get device level */
     241           0 :         (void)uoak_get_device_name(sc, target);
     242             : 
     243             :         /* get global sensor configuration */
     244           0 :         (void)uoak_get_report_mode(sc, target);
     245           0 :         (void)uoak_get_sample_rate(sc, target);
     246           0 :         (void)uoak_get_report_rate(sc, target);
     247             : 
     248             :         /* get device spcecific information */
     249           0 :         if (sc->sc_methods->dev_setting != NULL)
     250           0 :                 sc->sc_methods->dev_setting(sc->sc_parent, target);
     251           0 : }
     252             : 
     253             : void
     254           0 : uoak_print_devinfo(struct uoak_softc *sc)
     255             : {
     256           0 :         printf(": serial %s", sc->sc_udi.udi_serial);
     257           0 : }
     258             : 
     259             : void
     260           0 : uoak_print_setting(struct uoak_softc *sc, enum uoak_target target)
     261             : {
     262           0 :         switch (sc->sc_config[target].report_mode) {
     263             :         case OAK_REPORTMODE_AFTERSAMPLING:
     264           0 :                 printf(" sampling %dms",
     265           0 :                     sc->sc_config[target].sample_rate);
     266           0 :                 break;
     267             :         case OAK_REPORTMODE_AFTERCHANGE:
     268           0 :                 printf(" reports changes");
     269           0 :                 break;
     270             :         case OAK_REPORTMODE_FIXEDRATE:
     271           0 :                 printf(" rate %dms", 
     272           0 :                     sc->sc_config[target].report_rate);
     273           0 :                 break;
     274             :         default:
     275           0 :                 printf(" unknown sampling");
     276           0 :                 break;
     277             :         }
     278             : 
     279             :         /* print device spcecific information */
     280           0 :         if (sc->sc_methods->dev_print != NULL)
     281           0 :                 sc->sc_methods->dev_print(sc->sc_parent, target);
     282           0 :         printf("\n");
     283           0 : }
     284             : 
     285             : void
     286           0 : uoak_sensor_attach(struct uoak_softc *sc, struct uoak_sensor *s,
     287             :   enum sensor_type type)
     288             : {
     289           0 :         if (s == NULL)
     290             :                 return;
     291             : 
     292           0 :         s->avg.type = type;
     293           0 :         s->max.type = type;
     294           0 :         s->min.type = type;
     295           0 :         s->avg.flags |= SENSOR_FINVALID;
     296           0 :         s->max.flags |= SENSOR_FINVALID;
     297           0 :         s->min.flags |= SENSOR_FINVALID;
     298             : 
     299           0 :         (void)snprintf(s->avg.desc, sizeof(s->avg.desc),
     300           0 :             "avg(#%s)", sc->sc_udi.udi_serial);
     301           0 :         (void)snprintf(s->max.desc, sizeof(s->max.desc),
     302             :             "max(#%s)", sc->sc_udi.udi_serial);
     303           0 :         (void)snprintf(s->min.desc, sizeof(s->min.desc),
     304             :             "min(#%s)", sc->sc_udi.udi_serial);
     305             : 
     306           0 :         sensor_attach(sc->sc_sensordev, &s->avg);
     307           0 :         sensor_attach(sc->sc_sensordev, &s->max);
     308           0 :         sensor_attach(sc->sc_sensordev, &s->min);
     309           0 : }
     310             : 
     311             : void
     312           0 : uoak_sensor_detach(struct uoak_softc *sc, struct uoak_sensor *s)
     313             : {
     314           0 :         if (s == NULL)
     315             :                 return;
     316             : 
     317           0 :         sensor_attach(sc->sc_sensordev, &s->avg);
     318           0 :         sensor_attach(sc->sc_sensordev, &s->max);
     319           0 :         sensor_attach(sc->sc_sensordev, &s->min);
     320           0 : }
     321             : 
     322             : void
     323           0 : uoak_sensor_update(struct uoak_sensor *s, int val)
     324             : {
     325           0 :         if (s == NULL)
     326             :                 return;
     327             : 
     328             :         /* reset */
     329           0 :         if (s->count == 0) {
     330           0 :                 s->vmax = s->vmin = s->vavg = val;
     331           0 :                 s->count++;
     332           0 :                 return;
     333             :         }
     334             : 
     335             :         /* update min/max */
     336           0 :         if (val > s->vmax)
     337           0 :                 s->vmax = val;
     338           0 :         else if (val < s->vmin)
     339           0 :                 s->vmin = val;
     340             : 
     341             :         /* calc average */
     342           0 :         s->vavg = (s->vavg * s->count + val) / (s->count + 1);
     343             : 
     344           0 :         s->count++;
     345           0 : }
     346             : 
     347             : void
     348           0 : uoak_sensor_refresh(struct uoak_sensor *s, int mag, int offset)
     349             : {
     350           0 :         if (s == NULL)
     351             :                 return;
     352             :         /* update value */
     353           0 :         s->avg.value = s->vavg * mag + offset;
     354           0 :         s->max.value = s->vmax * mag + offset;
     355           0 :         s->min.value = s->vmin * mag + offset;
     356             : 
     357             :         /* update flag */
     358           0 :         s->avg.flags &= ~SENSOR_FINVALID;
     359           0 :         s->max.flags &= ~SENSOR_FINVALID;
     360           0 :         s->min.flags &= ~SENSOR_FINVALID;
     361           0 :         s->count = 0;
     362           0 : }
     363             : 

Generated by: LCOV version 1.13