adb_bt.c revision 1.3.4.1
11.3.4.1Syamt/*	$NetBSD: adb_bt.c,v 1.3.4.1 2008/05/16 02:23:53 yamt Exp $ */
21.1Smacallan
31.1Smacallan/*-
41.1Smacallan * Copyright (c) 2006 Michael Lorenz
51.1Smacallan * All rights reserved.
61.1Smacallan *
71.1Smacallan * Redistribution and use in source and binary forms, with or without
81.1Smacallan * modification, are permitted provided that the following conditions
91.1Smacallan * are met:
101.1Smacallan * 1. Redistributions of source code must retain the above copyright
111.1Smacallan *    notice, this list of conditions and the following disclaimer.
121.1Smacallan * 2. Redistributions in binary form must reproduce the above copyright
131.1Smacallan *    notice, this list of conditions and the following disclaimer in the
141.1Smacallan *    documentation and/or other materials provided with the distribution.
151.1Smacallan *
161.1Smacallan * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
171.1Smacallan * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
181.1Smacallan * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
191.1Smacallan * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
201.1Smacallan * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
211.1Smacallan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
221.1Smacallan * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
231.1Smacallan * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
241.1Smacallan * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
251.1Smacallan * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
261.1Smacallan * POSSIBILITY OF SUCH DAMAGE.
271.1Smacallan */
281.1Smacallan
291.1Smacallan#include <sys/cdefs.h>
301.3.4.1Syamt__KERNEL_RCSID(0, "$NetBSD: adb_bt.c,v 1.3.4.1 2008/05/16 02:23:53 yamt Exp $");
311.1Smacallan
321.1Smacallan#include <sys/param.h>
331.1Smacallan#include <sys/systm.h>
341.1Smacallan#include <sys/kernel.h>
351.1Smacallan#include <sys/device.h>
361.1Smacallan#include <sys/proc.h>
371.1Smacallan
381.1Smacallan#include <dev/wscons/wsconsio.h>
391.1Smacallan#include <dev/wscons/wskbdvar.h>
401.1Smacallan#include <dev/wscons/wsksymdef.h>
411.1Smacallan#include <dev/wscons/wsksymvar.h>
421.1Smacallan#include <dev/wscons/wsmousevar.h>
431.1Smacallan
441.1Smacallan#include <dev/sysmon/sysmonvar.h>
451.1Smacallan#include <dev/sysmon/sysmon_taskq.h>
461.1Smacallan
471.1Smacallan#include <machine/autoconf.h>
481.1Smacallan#include <machine/keyboard.h>
491.1Smacallan#include <machine/adbsys.h>
501.1Smacallan
511.1Smacallan#include <dev/adb/adbvar.h>
521.1Smacallan#include <dev/adb/adb_keymap.h>
531.1Smacallan
541.1Smacallan#include "opt_wsdisplay_compat.h"
551.1Smacallan#include "adbdebug.h"
561.1Smacallan
571.1Smacallan#ifdef ADBBT_DEBUG
581.1Smacallan#define DPRINTF printf
591.1Smacallan#else
601.1Smacallan#define DPRINTF while (0) printf
611.1Smacallan#endif
621.1Smacallan
631.1Smacallan#define BT_VOL_UP	0x06
641.1Smacallan#define BT_VOL_DOWN	0x07
651.1Smacallan#define BT_VOL_MUTE	0x08
661.1Smacallan#define BT_BRT_UP	0x09
671.1Smacallan#define BT_BRT_DOWN	0x0a
681.1Smacallan#define BT_EJECT	0x0b
691.1Smacallan#define BT_F7		0x0c
701.1Smacallan#define BT_NUMLOCK	0x7f
711.1Smacallan
721.2Smattstatic int adbbt_match(device_t, cfdata_t, void *);
731.2Smattstatic void adbbt_attach(device_t, device_t, void *);
741.1Smacallan
751.1Smacallanstruct adbbt_softc {
761.2Smatt	device_t sc_dev;
771.1Smacallan	struct adb_device *sc_adbdev;
781.1Smacallan	struct adb_bus_accessops *sc_ops;
791.2Smatt	device_t sc_wskbddev;
801.1Smacallan	int sc_msg_len;
811.1Smacallan	int sc_event;
821.1Smacallan	int sc_poll;
831.1Smacallan	int sc_polled_chars;
841.1Smacallan	int sc_rawkbd;
851.1Smacallan	uint8_t sc_buffer[16];
861.1Smacallan	uint8_t sc_pollbuf[16];
871.1Smacallan	uint8_t sc_trans[16];
881.1Smacallan	uint8_t sc_us;
891.1Smacallan};
901.1Smacallan
911.1Smacallan/* Driver definition. */
921.2SmattCFATTACH_DECL_NEW(adbbt, sizeof(struct adbbt_softc),
931.1Smacallan    adbbt_match, adbbt_attach, NULL, NULL);
941.1Smacallan
951.1Smacallanextern struct cfdriver adbbt_cd;
961.1Smacallan
971.1Smacallanstatic int adbbt_enable(void *, int);
981.1Smacallanstatic void adbbt_set_leds(void *, int);
991.1Smacallanstatic int adbbt_ioctl(void *, u_long, void *, int, struct lwp *);
1001.1Smacallanstatic void adbbt_handler(void *, int, uint8_t *);
1011.1Smacallan
1021.1Smacallanstruct wskbd_accessops adbbt_accessops = {
1031.1Smacallan	adbbt_enable,
1041.1Smacallan	adbbt_set_leds,
1051.1Smacallan	adbbt_ioctl,
1061.1Smacallan};
1071.1Smacallan
1081.1Smacallanstruct wskbd_mapdata adbbt_keymapdata = {
1091.1Smacallan	akbd_keydesctab,
1101.1Smacallan#ifdef AKBD_LAYOUT
1111.1Smacallan	AKBD_LAYOUT,
1121.1Smacallan#else
1131.1Smacallan	KB_US,
1141.1Smacallan#endif
1151.1Smacallan};
1161.1Smacallan
1171.1Smacallanstatic int
1181.2Smattadbbt_match(device_t parent, cfdata_t cf, void *aux)
1191.1Smacallan{
1201.1Smacallan	struct adb_attach_args *aaa = aux;
1211.1Smacallan
1221.1Smacallan	if ((aaa->dev->original_addr == ADBADDR_MISC) &&
1231.1Smacallan	    (aaa->dev->handler_id == 0x1f))
1241.1Smacallan		return 100;
1251.1Smacallan	else
1261.1Smacallan		return 0;
1271.1Smacallan}
1281.1Smacallan
1291.1Smacallanstatic void
1301.2Smattadbbt_attach(device_t parent, device_t self, void *aux)
1311.1Smacallan{
1321.2Smatt	struct adbbt_softc *sc = device_private(self);
1331.1Smacallan	struct adb_attach_args *aaa = aux;
1341.1Smacallan	struct wskbddev_attach_args a;
1351.1Smacallan
1361.2Smatt	sc->sc_dev = self;
1371.1Smacallan	sc->sc_ops = aaa->ops;
1381.1Smacallan	sc->sc_adbdev = aaa->dev;
1391.1Smacallan	sc->sc_adbdev->cookie = sc;
1401.1Smacallan	sc->sc_adbdev->handler = adbbt_handler;
1411.1Smacallan	sc->sc_us = ADBTALK(sc->sc_adbdev->current_addr, 0);
1421.1Smacallan
1431.1Smacallan	sc->sc_msg_len = 0;
1441.1Smacallan	sc->sc_rawkbd = 0;
1451.1Smacallan	sc->sc_trans[6]  = 96;	/* F5  */
1461.1Smacallan	sc->sc_trans[7]  = 118;	/* F4  */
1471.1Smacallan	sc->sc_trans[8]  = 99;	/* F3  */
1481.1Smacallan	sc->sc_trans[9]  = 120;	/* F2  */
1491.1Smacallan	sc->sc_trans[10] = 122;	/* F1  */
1501.1Smacallan	sc->sc_trans[11] = 111;	/* F12 */
1511.1Smacallan
1521.1Smacallan	printf(" addr %d: button device\n", sc->sc_adbdev->current_addr);
1531.1Smacallan
1541.1Smacallan	a.console = 0;
1551.1Smacallan	a.keymap = &adbbt_keymapdata;
1561.1Smacallan	a.accessops = &adbbt_accessops;
1571.1Smacallan	a.accesscookie = sc;
1581.1Smacallan
1591.1Smacallan	sc->sc_wskbddev = config_found_ia(self, "wskbddev", &a, wskbddevprint);
1601.1Smacallan}
1611.1Smacallan
1621.1Smacallanstatic void
1631.1Smacallanadbbt_handler(void *cookie, int len, uint8_t *data)
1641.1Smacallan{
1651.1Smacallan	struct adbbt_softc *sc = cookie;
1661.1Smacallan	int type;
1671.1Smacallan	uint8_t k, keyval, scancode;
1681.1Smacallan
1691.1Smacallan#ifdef ADBBT_DEBUG
1701.1Smacallan	int i;
1711.3Scegger	printf("%s: %02x - ", device_xname(&sc->sc_dev), sc->sc_us);
1721.1Smacallan	for (i = 0; i < len; i++) {
1731.1Smacallan		printf(" %02x", data[i]);
1741.1Smacallan	}
1751.1Smacallan	printf("\n");
1761.1Smacallan#endif
1771.1Smacallan	k = data[2];
1781.1Smacallan	keyval = ADBK_KEYVAL(k);
1791.1Smacallan	if ((keyval < 6) || (keyval > 0x0c))
1801.1Smacallan		return;
1811.1Smacallan	scancode = sc->sc_trans[keyval];
1821.1Smacallan
1831.1Smacallan#ifdef WSDISPLAY_COMPAT_RAWKBD
1841.1Smacallan	if (sc->sc_rawkbd) {
1851.1Smacallan		char cbuf[2];
1861.1Smacallan		int s;
1871.1Smacallan
1881.1Smacallan		cbuf[0] = scancode | (k & 0x80);
1891.1Smacallan
1901.1Smacallan		s = spltty();
1911.1Smacallan		wskbd_rawinput(sc->sc_wskbddev, cbuf, 1);
1921.1Smacallan		splx(s);
1931.1Smacallan	} else {
1941.1Smacallan#endif
1951.1Smacallan
1961.1Smacallan	/* normal event */
1971.1Smacallan	type = ADBK_PRESS(k) ?
1981.1Smacallan	    WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;
1991.1Smacallan	wskbd_input(sc->sc_wskbddev, type, scancode);
2001.1Smacallan#ifdef WSDISPLAY_COMPAT_RAWKBD
2011.1Smacallan	}
2021.1Smacallan#endif
2031.1Smacallan}
2041.1Smacallan
2051.1Smacallanstatic void
2061.1Smacallanadbbt_set_leds(void *cookie, int leds)
2071.1Smacallan{
2081.1Smacallan	/* we have no LEDs */
2091.1Smacallan}
2101.1Smacallan
2111.1Smacallanstatic int
2121.1Smacallanadbbt_enable(void *v, int on)
2131.1Smacallan{
2141.1Smacallan	return 0;
2151.1Smacallan}
2161.1Smacallan
2171.1Smacallanstatic int
2181.1Smacallanadbbt_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
2191.1Smacallan{
2201.1Smacallan#ifdef WSDISPLAY_COMPAT_RAWKBD
2211.1Smacallan	struct adbbt_softc *sc = (struct adbbt_softc *) v;
2221.1Smacallan#endif
2231.1Smacallan
2241.1Smacallan	switch (cmd) {
2251.1Smacallan
2261.1Smacallan	case WSKBDIO_GTYPE:
2271.1Smacallan		*(int *)data = WSKBD_TYPE_ADB;
2281.1Smacallan		return 0;
2291.1Smacallan#ifdef WSDISPLAY_COMPAT_RAWKBD
2301.1Smacallan	case WSKBDIO_SETMODE:
2311.1Smacallan		sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
2321.1Smacallan		return 0;
2331.1Smacallan#endif
2341.1Smacallan	}
2351.1Smacallan
2361.1Smacallan	return EPASSTHROUGH;
2371.1Smacallan}
238