Module Name: src Committed By: enami Date: Thu Mar 11 10:38:37 UTC 2010
Modified Files: src/distrib/sets/lists/man: mi src/share/man/man4: Makefile src/sys/dev: DEVNAMES src/sys/dev/usb: files.usb Added Files: src/share/man/man4: uyurex.4 src/sys/dev/usb: uyurex.c Log Message: Port uyurex(4) from OpenBSD. There is some XXX but works enough to play with it. To generate a diff of this commit: cvs rdiff -u -r1.1197 -r1.1198 src/distrib/sets/lists/man/mi cvs rdiff -u -r1.510 -r1.511 src/share/man/man4/Makefile cvs rdiff -u -r0 -r1.1 src/share/man/man4/uyurex.4 cvs rdiff -u -r1.257 -r1.258 src/sys/dev/DEVNAMES cvs rdiff -u -r1.96 -r1.97 src/sys/dev/usb/files.usb cvs rdiff -u -r0 -r1.1 src/sys/dev/usb/uyurex.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/sets/lists/man/mi diff -u src/distrib/sets/lists/man/mi:1.1197 src/distrib/sets/lists/man/mi:1.1198 --- src/distrib/sets/lists/man/mi:1.1197 Mon Mar 8 06:40:07 2010 +++ src/distrib/sets/lists/man/mi Thu Mar 11 10:38:36 2010 @@ -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 Index: src/share/man/man4/Makefile diff -u src/share/man/man4/Makefile:1.510 src/share/man/man4/Makefile:1.511 --- src/share/man/man4/Makefile:1.510 Sat Mar 6 21:05:36 2010 +++ src/share/man/man4/Makefile Thu Mar 11 10:38:37 2010 @@ -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 @@ 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 Index: src/sys/dev/DEVNAMES diff -u src/sys/dev/DEVNAMES:1.257 src/sys/dev/DEVNAMES:1.258 --- src/sys/dev/DEVNAMES:1.257 Sat Mar 6 21:05:36 2010 +++ src/sys/dev/DEVNAMES Thu Mar 11 10:38:37 2010 @@ -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 @@ uvisor MI uvscom MI uyap MI +uyurex MI va vax vcons MI Attribute veriexec MI Index: src/sys/dev/usb/files.usb diff -u src/sys/dev/usb/files.usb:1.96 src/sys/dev/usb/files.usb:1.97 --- src/sys/dev/usb/files.usb:1.96 Sat Mar 6 21:05:37 2010 +++ src/sys/dev/usb/files.usb Thu Mar 11 10:38:37 2010 @@ -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 @@ 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 Added files: Index: src/share/man/man4/uyurex.4 diff -u /dev/null src/share/man/man4/uyurex.4:1.1 --- /dev/null Thu Mar 11 10:38:37 2010 +++ src/share/man/man4/uyurex.4 Thu Mar 11 10:38:37 2010 @@ -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 <y...@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 y...@nui.org . Index: src/sys/dev/usb/uyurex.c diff -u /dev/null src/sys/dev/usb/uyurex.c:1.1 --- /dev/null Thu Mar 11 10:38:37 2010 +++ src/sys/dev/usb/uyurex.c Thu Mar 11 10:38:37 2010 @@ -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 <y...@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); +}