xref: /openbsd-src/sys/dev/i2c/icc.c (revision d27ecf16d2ff08a0f90dc58b618b3644d2dca279)
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