Port uyurex(4) from OpenBSD. There is some XXX but works enough to

play with it.
This commit is contained in:
enami 2010-03-11 10:38:36 +00:00
parent 9ef501d113
commit b624a04f14
6 changed files with 443 additions and 5 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.1197 2010/03/08 06:40:07 lukem Exp $
# $NetBSD: mi,v 1.1198 2010/03/11 10:38:36 enami Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@ -1616,6 +1616,7 @@
./usr/share/man/cat4/uvisor.0 man-sys-catman .cat
./usr/share/man/cat4/uvscom.0 man-sys-catman .cat
./usr/share/man/cat4/uyap.0 man-sys-catman .cat
./usr/share/man/cat4/uyurex.0 man-sys-catman .cat
./usr/share/man/cat4/vax/acc.0 man-sys-catman .cat
./usr/share/man/cat4/vax/ad.0 man-sys-catman .cat
./usr/share/man/cat4/vax/asc.0 man-sys-catman .cat
@ -4190,6 +4191,7 @@
./usr/share/man/html4/uvisor.html man-sys-htmlman html
./usr/share/man/html4/uvscom.html man-sys-htmlman html
./usr/share/man/html4/uyap.html man-sys-htmlman html
./usr/share/man/html4/uyurex.html man-sys-htmlman html
./usr/share/man/html4/vax/acc.html man-sys-htmlman html
./usr/share/man/html4/vax/ad.html man-sys-htmlman html
./usr/share/man/html4/vax/asc.html man-sys-htmlman html
@ -6694,6 +6696,7 @@
./usr/share/man/man4/uvisor.4 man-sys-man .man
./usr/share/man/man4/uvscom.4 man-sys-man .man
./usr/share/man/man4/uyap.4 man-sys-man .man
./usr/share/man/man4/uyurex.4 man-sys-man .man
./usr/share/man/man4/vax/acc.4 man-sys-man .man
./usr/share/man/man4/vax/ad.4 man-sys-man .man
./usr/share/man/man4/vax/asc.4 man-sys-man .man

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.510 2010/03/06 21:05:36 plunky Exp $
# $NetBSD: Makefile,v 1.511 2010/03/11 10:38:37 enami Exp $
# @(#)Makefile 8.1 (Berkeley) 6/18/93
MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 acpidalb.4 \
@ -72,7 +72,7 @@ MAN+= stuirda.4 u3g.4 uaudio.4 uberry.4 ubsa.4 ubt.4 uchcom.4 ucom.4 ucycom.4 \
umass.4 umct.4 umidi.4 umodem.4 ums.4 uplcom.4 urio.4 usb.4 \
uscanner.4 uslsa.4 usscanner.4 ustir.4 uvisor.4 uvscom.4 uyap.4 \
aue.4 atu.4 axe.4 cdce.4 cue.4 kue.4 upl.4 url.4 udav.4 \
ehci.4 ohci.4 slhci.4 uhci.4 uthum.4 utoppy.4 uvideo.4
ehci.4 ohci.4 slhci.4 uhci.4 uthum.4 utoppy.4 uvideo.4 uyurex.4
# Ir devices
MAN+= irframe.4 cir.4 irframetty.4 oboe.4

53
share/man/man4/uyurex.4 Normal file
View File

@ -0,0 +1,53 @@
.\" $NetBSD: uyurex.4,v 1.1 2010/03/11 10:38:37 enami Exp $
.\" $OpenBSD: uyurex.4,v 1.2 2010/03/01 09:36:24 jmc Exp $
.\"
.\" Copyright (c) 2010 Yojiro UO <yuo@nui.org>
.\"
.\" 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 March 11, 2010
.Dt UYUREX 4
.Os
.Sh NAME
.Nm uyurex
.Nd YUREX USB twitch/jiggle of knee sensor
.Sh SYNOPSIS
.Cd "uyurex* at uhidev? reportid ?"
.Sh DESCRIPTION
The
.Nm
driver provides support for the Maywa-denki & KAYAC YUREX device.
The device has a sensor to count user's leg twitch and it
possesses a collection of sensor values which are
made available through the
.Xr envstat 8
command.
The counter unit for twitch is "BBU" (BinBo-YUsuri or
Bounding Body from Unconciousness) and the unit for BBU speed
is "mBBU/sec" (milli BBU per second).
.Sh SEE ALSO
.Xr envsys 4 ,
.Xr intro 4 ,
.Xr uhidev 4 ,
.Xr envstat 8 ,
.Xr sysmon_envsys 9
.Rs
.%T The YUREX Web Page
.%O http://bbu.kayac.com/en/about/
.Re
.Sh AUTHORS
.An -nosplit
The
.Nm
driver was written by
.An Yojiro UO Aq yuo@nui.org .

View File

@ -1,4 +1,4 @@
# $NetBSD: DEVNAMES,v 1.257 2010/03/06 21:05:36 plunky Exp $
# $NetBSD: DEVNAMES,v 1.258 2010/03/11 10:38:37 enami Exp $
#
# This file contains all used device names and defined attributes in
# alphabetical order. New devices added to the system somewhere should first
@ -1377,6 +1377,7 @@ uu vax
uvisor MI
uvscom MI
uyap MI
uyurex MI
va vax
vcons MI Attribute
veriexec MI

View File

@ -1,4 +1,4 @@
# $NetBSD: files.usb,v 1.96 2010/03/06 21:05:37 plunky Exp $
# $NetBSD: files.usb,v 1.97 2010/03/11 10:38:37 enami Exp $
#
# Config file and device description for machine-independent USB code.
# Included by ports that need it. Ports that use it must provide
@ -346,3 +346,8 @@ file dev/usb/udl.c udl
device uhso: ifnet
attach uhso at usbdevif
file dev/usb/uhso.c uhso
# Maywa-denki/Kayac YUREX
device uyurex: hid
attach uyurex at uhidbus
file dev/usb/uyurex.c uyurex

376
sys/dev/usb/uyurex.c Normal file
View File

@ -0,0 +1,376 @@
/* $NetBSD: uyurex.c,v 1.1 2010/03/11 10:38:37 enami Exp $ */
/* $OpenBSD: uyurex.c,v 1.3 2010/03/04 03:47:22 deraadt Exp $ */
/*
* Copyright (c) 2010 Yojiro UO <yuo@nui.org>
*
* 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 Maywa-Denki & KAYAC YUREX BBU sensor */
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/device.h>
#include <sys/conf.h>
#include <sys/envsys.h>
#include <dev/sysmon/sysmonvar.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbhid.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdevs.h>
#include <dev/usb/uhidev.h>
#include <dev/usb/hid.h>
#ifdef USB_DEBUG
#define UYUREX_DEBUG
#endif
#define CMD_NONE 0xf0
#define CMD_EOF 0x0d
#define CMD_ACK 0x21
#define CMD_MODE 0x41 /* XXX */
#define CMD_VALUE 0x43
#define CMD_READ 0x52
#define CMD_WRITE 0x53
#define CMD_PADDING 0xff
#define UPDATE_TICK 5 /* sec */
#ifdef UYUREX_DEBUG
int uyurexdebug = 0;
#define DPRINTFN(n, x) do { if (uyurexdebug > (n)) printf x; } while (0)
#else
#define DPRINTFN(n, x)
#endif
#define DPRINTF(x) DPRINTFN(0, x)
struct uyurex_softc {
struct uhidev sc_hdev;
usbd_device_handle sc_udev;
u_char sc_dying;
uint16_t sc_flag;
/* uhidev parameters */
size_t sc_flen; /* feature report length */
size_t sc_ilen; /* input report length */
size_t sc_olen; /* output report length */
uint8_t *sc_ibuf;
/* sensor framework */
struct sysmon_envsys *sc_sme;
envsys_data_t sc_sensor_val;
envsys_data_t sc_sensor_delta;
/* device private */
int sc_initialized;
uint8_t issueing_cmd;
uint8_t accepted_cmd;
uint32_t sc_curval;
uint32_t sc_oldval;
callout_t sc_deltach;
};
const struct usb_devno uyurex_devs[] = {
{ USB_VENDOR_MICRODIA, USB_PRODUCT_MICRODIA_YUREX },
};
#define uyurex_lookup(v, p) usb_lookup(uyurex_devs, v, p)
int uyurex_match(device_t, cfdata_t, void *);
void uyurex_attach(device_t, device_t, void *);
int uyurex_detach(device_t, int);
int uyurex_activate(device_t, enum devact);
void uyurex_set_mode(struct uyurex_softc *, uint8_t);
void uyurex_read_value_request(struct uyurex_softc *);
void uyurex_write_value_request(struct uyurex_softc *, uint32_t);
void uyurex_intr(struct uhidev *, void *, u_int);
static void uyurex_refresh(struct sysmon_envsys *, envsys_data_t *);
static void uyurex_delta(void *);
extern struct cfdriver uyurex_cd;
CFATTACH_DECL_NEW(uyurex, sizeof(struct uyurex_softc),
uyurex_match, uyurex_attach, uyurex_detach, uyurex_activate);
USB_MATCH(uyurex)
{
USB_MATCH_START(uyurex, uaa);
struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
if (uyurex_lookup(uha->uaa->vendor, uha->uaa->product) == NULL)
return UMATCH_NONE;
return (UMATCH_VENDOR_PRODUCT);
}
USB_ATTACH(uyurex)
{
USB_ATTACH_START(uyurex, sc, uaa);
struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
usbd_device_handle dev = uha->parent->sc_udev;
int size, repid, err;
void *desc;
sc->sc_udev = dev;
sc->sc_hdev.sc_dev = self;
sc->sc_hdev.sc_intr = uyurex_intr;
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_hdev.sc_report_id = uha->reportid;
uhidev_get_report_desc(uha->parent, &desc, &size);
repid = uha->reportid;
sc->sc_ilen = hid_report_size(desc, size, hid_input, repid);
sc->sc_olen = hid_report_size(desc, size, hid_output, repid);
sc->sc_flen = hid_report_size(desc, size, hid_feature, repid);
aprint_normal("\n");
aprint_naive("\n");
err = uhidev_open(&sc->sc_hdev);
if (err) {
aprint_error_dev(self, "uyurex_open: uhidev_open %d\n", err);
return;
}
sc->sc_ibuf = malloc(sc->sc_ilen, M_USBDEV, M_WAITOK);
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
sc->sc_hdev.sc_dev);
/* attach sensor */
sc->sc_sme = sysmon_envsys_create();
/* error handling? XXX */
sc->sc_sme->sme_name = device_xname(self);
/* add BBU sensor */
sc->sc_sensor_val.units = ENVSYS_INTEGER;
sc->sc_sensor_val.state = ENVSYS_SINVALID;
sc->sc_sensor_val.flags = ENVSYS_FMONCRITICAL; /* abuse XXX */
sc->sc_sensor_val.monitor = true;
strlcpy(sc->sc_sensor_val.desc, "BBU",
sizeof(sc->sc_sensor_val.desc));
sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor_val);
/* add BBU delta sensor */
sc->sc_sensor_delta.units = ENVSYS_INTEGER;
sc->sc_sensor_delta.state = ENVSYS_SINVALID;
strlcpy(sc->sc_sensor_delta.desc, "mBBU/sec",
sizeof(sc->sc_sensor_delta.desc));
sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor_delta);
sc->sc_sme->sme_cookie = sc;
sc->sc_sme->sme_refresh = uyurex_refresh;
sc->sc_sme->sme_events_timeout = UPDATE_TICK;
sc->sc_sme->sme_flags = SME_INIT_REFRESH;
if (sysmon_envsys_register(sc->sc_sme)) {
aprint_error_dev(self, "unable to register with sysmon\n");
sysmon_envsys_destroy(sc->sc_sme);
}
callout_init(&sc->sc_deltach, 0);
callout_reset(&sc->sc_deltach, UPDATE_TICK * hz, uyurex_delta, sc);
DPRINTF(("uyurex_attach: complete\n"));
/* init device */ /* XXX */
uyurex_set_mode(sc, 0);
}
USB_DETACH(uyurex)
{
USB_DETACH_START(uyurex, sc);
int rv = 0;
sc->sc_dying = 1;
callout_halt(&sc->sc_deltach, NULL);
callout_destroy(&sc->sc_deltach);
sysmon_envsys_unregister(sc->sc_sme);
if (sc->sc_ibuf != NULL) {
free(sc->sc_ibuf, M_USBDEV);
sc->sc_ibuf = NULL;
}
usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
sc->sc_hdev.sc_dev);
return (rv);
}
int
uyurex_activate(device_t self, enum devact act)
{
struct uyurex_softc *sc = device_private(self);
switch (act) {
case DVACT_DEACTIVATE:
sc->sc_dying = 1;
break;
}
return (0);
}
void
uyurex_intr(struct uhidev *addr, void *ibuf, u_int len)
{
struct uyurex_softc *sc = (struct uyurex_softc *)addr;
uint8_t buf[8];
uint32_t val;
if (sc->sc_ibuf == NULL)
return;
/* process requests */
memcpy(buf, ibuf, 8);
DPRINTF(("intr: %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n",
buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7]));
switch (buf[0]) {
case CMD_ACK:
if (buf[1] == sc->issueing_cmd) {
DPRINTF(("ack recieved for cmd 0x%.2x\n", buf[1]));
sc->accepted_cmd = buf[1];
} else {
DPRINTF(("cmd-ack mismatch: recved 0x%.2x, expect 0x%.2x\n",
buf[1], sc->issueing_cmd));
/* discard previous command */
sc->accepted_cmd = CMD_NONE;
sc->issueing_cmd = CMD_NONE;
}
break;
case CMD_READ:
case CMD_VALUE:
val = (buf[2] << 24) + (buf[3] << 16) + (buf[4] << 8) + buf[5];
if (!sc->sc_initialized) {
sc->sc_oldval = val;
sc->sc_initialized = 1;
}
sc->sc_sensor_val.value_cur = val;
sc->sc_sensor_val.state = ENVSYS_SVALID;
sc->sc_curval = val;
DPRINTF(("recv value update message: %d\n", val));
break;
default:
DPRINTF(("unknown message: 0x%.2x\n", buf[0]));
}
return;
}
static void
uyurex_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
{
struct uyurex_softc *sc = sme->sme_cookie;
DPRINTF(("refresh: edata = %p\n", edata));
if (edata != &sc->sc_sensor_val)
return;
if (!sc->sc_initialized) {
DPRINTF(("refresh: notinit\n"));
uyurex_read_value_request(sc);
}
}
static void
uyurex_delta(void *arg)
{
struct uyurex_softc *sc = arg;
envsys_data_t *edata = &sc->sc_sensor_delta;
/* calculate delta value */
edata->value_cur =
(1000 * (sc->sc_curval - sc->sc_oldval)) / UPDATE_TICK;
edata->state = ENVSYS_SVALID;
#if 0
DPRINTF(("delta: update: %d -> %d\n", sc->sc_oldval, sc->sc_curval));
#endif
sc->sc_oldval = sc->sc_curval;
callout_reset(&sc->sc_deltach, UPDATE_TICK * hz, uyurex_delta, sc);
}
void
uyurex_set_mode(struct uyurex_softc *sc, uint8_t val)
{
uint8_t req[8];
usbd_status err;
memset(req, CMD_PADDING, sizeof(req));
req[0] = CMD_MODE;
req[1] = val;
req[2] = CMD_EOF;
sc->issueing_cmd = CMD_MODE; /* necessary? */
sc->accepted_cmd = CMD_NONE; /* necessary? */
err = uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, req,
sc->sc_olen);
if (err) {
printf("uhidev_set_report error:EIO\n");
return;
}
/* wait ack */
tsleep(&sc->sc_sme, 0, "uyurex", (1000*hz+999)/1000 + 1);
}
void
uyurex_read_value_request(struct uyurex_softc *sc)
{
uint8_t req[8];
memset(req, CMD_PADDING, sizeof(req));
req[0] = CMD_READ;
req[1] = CMD_EOF;
sc->issueing_cmd = CMD_READ;
sc->accepted_cmd = CMD_NONE;
if (uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, req,
sc->sc_olen))
return;
/* wait till sensor data are updated, 500ms will be enough */
tsleep(&sc->sc_sme, 0, "uyurex", (500*hz+999)/1000 + 1);
}
void
uyurex_write_value_request(struct uyurex_softc *sc, uint32_t val)
{
uint32_t v;
uint8_t req[8];
req[0] = CMD_WRITE;
req[1] = 0;
req[6] = CMD_EOF;
req[7] = CMD_PADDING;
v = htobe32(val);
memcpy(req + 2, &v, sizeof(uint32_t));
sc->issueing_cmd = CMD_WRITE;
sc->accepted_cmd = CMD_NONE;
if (uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, req,
sc->sc_olen))
return;
/* wait till sensor data are updated, 250ms will be enough */
tsleep(&sc->sc_sme, 0, "uyurex", (250*hz+999)/1000 + 1);
}