1*d27ecf16Sderaadt /* $OpenBSD: icc.c,v 1.2 2024/08/17 15:10:00 deraadt Exp $ */ 22022a111Smatthieu 32022a111Smatthieu /* 42022a111Smatthieu * Copyright (c) 2021 Anton Lindqvist <anton@openbsd.org> 52022a111Smatthieu * Copyright (c) 2022 Matthieu Herrb <matthieu@openbsd.org> 62022a111Smatthieu * 72022a111Smatthieu * Permission to use, copy, modify, and distribute this software for any 82022a111Smatthieu * purpose with or without fee is hereby granted, provided that the above 92022a111Smatthieu * copyright notice and this permission notice appear in all copies. 102022a111Smatthieu * 112022a111Smatthieu * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 122022a111Smatthieu * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 132022a111Smatthieu * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 142022a111Smatthieu * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 152022a111Smatthieu * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 162022a111Smatthieu * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 172022a111Smatthieu * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 182022a111Smatthieu */ 192022a111Smatthieu 202022a111Smatthieu #include <sys/param.h> 212022a111Smatthieu #include <sys/systm.h> 222022a111Smatthieu #include <sys/device.h> 232022a111Smatthieu 242022a111Smatthieu #include <dev/i2c/i2cvar.h> 252022a111Smatthieu #include <dev/i2c/ihidev.h> 262022a111Smatthieu 272022a111Smatthieu #include <dev/hid/hid.h> 282022a111Smatthieu #include <dev/hid/hidccvar.h> 292022a111Smatthieu 302022a111Smatthieu struct icc_softc { 312022a111Smatthieu struct ihidev sc_hdev; 322022a111Smatthieu struct hidcc *sc_cc; 332022a111Smatthieu int sc_keydown; 342022a111Smatthieu }; 352022a111Smatthieu 362022a111Smatthieu int icc_match(struct device *, void *, void *); 372022a111Smatthieu void icc_attach(struct device *, struct device *, void *); 382022a111Smatthieu int icc_detach(struct device *, int); 392022a111Smatthieu void icc_intr(struct ihidev *, void *, u_int); 402022a111Smatthieu 412022a111Smatthieu int icc_enable(void *, int); 422022a111Smatthieu 432022a111Smatthieu struct cfdriver icc_cd = { 442022a111Smatthieu NULL, "icc", DV_DULL 452022a111Smatthieu }; 462022a111Smatthieu 472022a111Smatthieu const struct cfattach icc_ca = { 482022a111Smatthieu sizeof(struct icc_softc), 492022a111Smatthieu icc_match, 502022a111Smatthieu icc_attach, 51*d27ecf16Sderaadt icc_detach 522022a111Smatthieu }; 532022a111Smatthieu 542022a111Smatthieu int 552022a111Smatthieu icc_match(struct device *parent, void *match, void *aux) 562022a111Smatthieu { 572022a111Smatthieu struct ihidev_attach_arg *iha = aux; 582022a111Smatthieu void *desc; 592022a111Smatthieu int size; 602022a111Smatthieu 612022a111Smatthieu if (iha->reportid == IHIDEV_CLAIM_MULTIPLEID) 622022a111Smatthieu return IMATCH_NONE; 632022a111Smatthieu 642022a111Smatthieu ihidev_get_report_desc(iha->parent, &desc, &size); 652022a111Smatthieu if (hid_report_size(desc, size, hid_input, iha->reportid) == 0) 662022a111Smatthieu return IMATCH_NONE; 672022a111Smatthieu 682022a111Smatthieu if (!hidcc_match(desc, size, iha->reportid)) 692022a111Smatthieu return IMATCH_NONE; 702022a111Smatthieu return IMATCH_IFACECLASS; 712022a111Smatthieu } 722022a111Smatthieu 732022a111Smatthieu void 742022a111Smatthieu icc_attach(struct device *parent, struct device *self, void *aux) 752022a111Smatthieu { 762022a111Smatthieu struct icc_softc *sc = (struct icc_softc *)self; 772022a111Smatthieu struct ihidev_attach_arg *iha = aux; 782022a111Smatthieu void *desc; 792022a111Smatthieu int repid, size; 802022a111Smatthieu 812022a111Smatthieu sc->sc_hdev.sc_intr = icc_intr; 822022a111Smatthieu sc->sc_hdev.sc_parent = iha->parent; 832022a111Smatthieu sc->sc_hdev.sc_report_id = iha->reportid; 842022a111Smatthieu 852022a111Smatthieu ihidev_get_report_desc(iha->parent, &desc, &size); 862022a111Smatthieu repid = iha->reportid; 872022a111Smatthieu sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid); 882022a111Smatthieu sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid); 892022a111Smatthieu sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid); 902022a111Smatthieu 912022a111Smatthieu struct hidcc_attach_arg hca = { 922022a111Smatthieu .device = &sc->sc_hdev.sc_idev, 932022a111Smatthieu .audio_cookie = iha->iaa->ia_cookie, 942022a111Smatthieu .desc = desc, 952022a111Smatthieu .descsiz = size, 962022a111Smatthieu .repid = repid, 972022a111Smatthieu .isize = sc->sc_hdev.sc_isize, 982022a111Smatthieu .enable = icc_enable, 992022a111Smatthieu .arg = self, 1002022a111Smatthieu }; 1012022a111Smatthieu sc->sc_cc = hidcc_attach(&hca); 1022022a111Smatthieu } 1032022a111Smatthieu 1042022a111Smatthieu int 1052022a111Smatthieu icc_detach(struct device *self, int flags) 1062022a111Smatthieu { 1072022a111Smatthieu struct icc_softc *sc = (struct icc_softc *)self; 1082022a111Smatthieu int error = 0; 1092022a111Smatthieu 1102022a111Smatthieu ihidev_close(&sc->sc_hdev); 1112022a111Smatthieu if (sc->sc_cc != NULL) 1122022a111Smatthieu error = hidcc_detach(sc->sc_cc, flags); 1132022a111Smatthieu return error; 1142022a111Smatthieu } 1152022a111Smatthieu 1162022a111Smatthieu void 1172022a111Smatthieu icc_intr(struct ihidev *addr, void *data, u_int len) 1182022a111Smatthieu { 1192022a111Smatthieu struct icc_softc *sc = (struct icc_softc *)addr; 1202022a111Smatthieu 1212022a111Smatthieu if (sc->sc_cc != NULL) 1222022a111Smatthieu hidcc_intr(sc->sc_cc, data, len); 1232022a111Smatthieu } 1242022a111Smatthieu 1252022a111Smatthieu int 1262022a111Smatthieu icc_enable(void *v, int on) 1272022a111Smatthieu { 1282022a111Smatthieu struct icc_softc *sc = v; 1292022a111Smatthieu int error = 0; 1302022a111Smatthieu 1312022a111Smatthieu if (on) 1322022a111Smatthieu error = ihidev_open(&sc->sc_hdev); 1332022a111Smatthieu else 1342022a111Smatthieu ihidev_close(&sc->sc_hdev); 1352022a111Smatthieu return error; 1362022a111Smatthieu } 137