Module Name: src Committed By: jmcneill Date: Mon Dec 9 22:05:17 UTC 2024
Modified Files: src/sys/dev/i2c: files.i2c Added Files: src/sys/dev/i2c: ikbd.c Log Message: Import ikbd(4) from OpenBSD. To generate a diff of this commit: cvs rdiff -u -r1.128 -r1.129 src/sys/dev/i2c/files.i2c cvs rdiff -u -r0 -r1.1 src/sys/dev/i2c/ikbd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/i2c/files.i2c diff -u src/sys/dev/i2c/files.i2c:1.128 src/sys/dev/i2c/files.i2c:1.129 --- src/sys/dev/i2c/files.i2c:1.128 Sun Dec 8 20:49:56 2024 +++ src/sys/dev/i2c/files.i2c Mon Dec 9 22:05:17 2024 @@ -1,4 +1,4 @@ -# $NetBSD: files.i2c,v 1.128 2024/12/08 20:49:56 jmcneill Exp $ +# $NetBSD: files.i2c,v 1.129 2024/12/09 22:05:17 jmcneill Exp $ obsolete defflag opt_i2cbus.h I2C_SCAN define i2cbus { } @@ -328,16 +328,21 @@ device ihidev: hid, ihidbus, gpio attach ihidev at iic file dev/i2c/ihidev.c ihidev -#HID mice +# HID mice device ims: hid, hidms, wsmousedev attach ims at ihidbus file dev/i2c/ims.c ims -#HID multitouch +# HID multitouch device imt: hid, hidmt, wsmousedev attach imt at ihidbus file dev/i2c/imt.c imt +# HID keyboard +device ikbd: hid, hidkbd, wskbddev +attach ikbd at ihidbus +file dev/i2c/ikbd.c ikbd + # Taos TSL256x ambient light sensor device tsllux: sysmon_envsys attach tsllux at iic Added files: Index: src/sys/dev/i2c/ikbd.c diff -u /dev/null src/sys/dev/i2c/ikbd.c:1.1 --- /dev/null Mon Dec 9 22:05:17 2024 +++ src/sys/dev/i2c/ikbd.c Mon Dec 9 22:05:17 2024 @@ -0,0 +1,212 @@ +/* $NetBSD: ikbd.c,v 1.1 2024/12/09 22:05:17 jmcneill Exp $ */ + +/* $OpenBSD: ikbd.c,v 1.2 2022/09/03 15:48:16 kettenis Exp $ */ +/* + * HID-over-i2c keyboard driver + * + * Copyright (c) 2016 Mark Kettenis <kette...@openbsd.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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/ioctl.h> + +#include <dev/i2c/i2cvar.h> +#include <dev/i2c/ihidev.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wskbdvar.h> +#include <dev/wscons/wsksymdef.h> + +#include <dev/hid/hid.h> +#include <dev/hid/hidkbdsc.h> + +extern const struct wscons_keydesc hidkbd_keydesctab[]; +static struct wskbd_mapdata ikbd_keymapdata = { + hidkbd_keydesctab, + KB_US, +}; + +struct ikbd_softc { + struct ihidev sc_hdev; + struct hidkbd sc_kbd; + int sc_spl; +}; + +void ikbd_intr(struct ihidev *addr, void *ibuf, u_int len); + +void ikbd_cngetc(void *, u_int *, int *); +void ikbd_cnpollc(void *, int); + +const struct wskbd_consops ikbd_consops = { + .getc = ikbd_cngetc, + .pollc = ikbd_cnpollc, + .bell = NULL, +}; + +int ikbd_enable(void *, int); +void ikbd_set_leds(void *, int); +int ikbd_ioctl(void *, u_long, void *, int, lwp_t *); + +const struct wskbd_accessops ikbd_accessops = { + .enable = ikbd_enable, + .set_leds = ikbd_set_leds, + .ioctl = ikbd_ioctl, +}; + +int ikbd_match(device_t, cfdata_t, void *); +void ikbd_attach(device_t, device_t, void *); +int ikbd_detach(device_t, int); + +CFATTACH_DECL_NEW(ikbd, sizeof(struct ikbd_softc), + ikbd_match, ikbd_attach, ikbd_detach, NULL); + +int +ikbd_match(device_t parent, cfdata_t match, void *aux) +{ + struct ihidev_attach_arg *iha = aux; + int size; + void *desc; + + ihidev_get_report_desc(iha->parent, &desc, &size); + if (!hid_is_collection(desc, size, iha->reportid, + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD))) + return (IMATCH_NONE); + + return (IMATCH_IFACECLASS); +} + +void +ikbd_attach(device_t parent, device_t self, void *aux) +{ + struct ikbd_softc *sc = device_private(self); + struct hidkbd *kbd = &sc->sc_kbd; + struct ihidev_attach_arg *iha = (struct ihidev_attach_arg *)aux; + int dlen, repid; + void *desc; + + sc->sc_hdev.sc_idev = self; + sc->sc_hdev.sc_intr = ikbd_intr; + sc->sc_hdev.sc_parent = iha->parent; + sc->sc_hdev.sc_report_id = iha->reportid; + + ihidev_get_report_desc(iha->parent, &desc, &dlen); + repid = iha->reportid; + sc->sc_hdev.sc_isize = hid_report_size(desc, dlen, hid_input, repid); + sc->sc_hdev.sc_osize = hid_report_size(desc, dlen, hid_output, repid); + sc->sc_hdev.sc_fsize = hid_report_size(desc, dlen, hid_feature, repid); + + if (hidkbd_attach(self, kbd, 1, 0, repid, desc, dlen) != 0) + return; + + aprint_naive("\n"); + aprint_normal("\n"); + + if (kbd->sc_console_keyboard) { + wskbd_cnattach(&ikbd_consops, sc, &ikbd_keymapdata); + ikbd_enable(sc, 1); + } + + hidkbd_attach_wskbd(kbd, KB_US, &ikbd_accessops); +} + +int +ikbd_detach(device_t self, int flags) +{ + struct ikbd_softc *sc = device_private(self); + struct hidkbd *kbd = &sc->sc_kbd; + + return hidkbd_detach(kbd, flags); +} + +void +ikbd_intr(struct ihidev *addr, void *ibuf, u_int len) +{ + struct ikbd_softc *sc = (struct ikbd_softc *)addr; + struct hidkbd *kbd = &sc->sc_kbd; + + if (kbd->sc_enabled != 0) + hidkbd_input(kbd, (uint8_t *)ibuf, len); +} + +int +ikbd_enable(void *v, int on) +{ + struct ikbd_softc *sc = v; + struct hidkbd *kbd = &sc->sc_kbd; + int rv; + + if ((rv = hidkbd_enable(kbd, on)) != 0) + return rv; + + if (on) { + return ihidev_open(&sc->sc_hdev); + } else { + ihidev_close(&sc->sc_hdev); + return 0; + } +} + +void +ikbd_set_leds(void *v, int leds) +{ +} + +int +ikbd_ioctl(void *v, u_long cmd, void *data, int flag, lwp_t *l) +{ + struct ikbd_softc *sc = v; + struct hidkbd *kbd = &sc->sc_kbd; + + switch (cmd) { + case WSKBDIO_GTYPE: + /* XXX: should we set something else? */ + *(u_int *)data = WSKBD_TYPE_USB; + return 0; + default: + return hidkbd_ioctl(kbd, cmd, data, flag, l); + } +} + +/* Console interface. */ +void +ikbd_cngetc(void *v, u_int *type, int *data) +{ + struct ikbd_softc *sc = v; + struct hidkbd *kbd = &sc->sc_kbd; + + kbd->sc_polling = 1; +#if notyet + while (kbd->sc_npollchar <= 0) { + ihidev_poll(sc->sc_hdev.sc_parent); + delay(1000); + } +#endif + kbd->sc_polling = 0; + hidkbd_cngetc(kbd, type, data); +} + +void +ikbd_cnpollc(void *v, int on) +{ + struct ikbd_softc *sc = v; + + if (on) + sc->sc_spl = spltty(); + else + splx(sc->sc_spl); +}