/* $NetBSD: hilms.c,v 1.7 2023/05/11 09:35:57 martin Exp $ */
/* $OpenBSD: hilms.c,v 1.5 2007/04/10 22:37:17 miod Exp $ */
/*
* Copyright (c) 2003, Miodrag Vallat.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* Reject anything that has only buttons - they are handled as
* keyboards, really.
*/
if (ha->ha_infolen > 1 && (ha->ha_info[1] & HIL_AXMASK) == 0)
return 0;
void
hilms_callback(struct hildev_softc *hdsc, u_int buflen, uint8_t *buf)
{
struct hilms_softc *sc = device_private(hdsc->sc_dev);
int type, flags;
int dx, dy, dz, button;
#ifdef DIAGNOSTIC
int minlen;
#endif
/*
* Ignore packet if we don't need it
*/
if (sc->sc_enabled == 0)
return;
type = *buf++;
#ifdef DIAGNOSTIC
/*
* Check that the packet contains all the expected data,
* ignore it if too short.
*/
minlen = 1;
if (type & HIL_MOUSEMOTION) {
minlen += sc->sc_axes <<
(sc->sc_features & HIL_16_BITS) ? 1 : 0;
}
if (type & HIL_MOUSEBUTTON)
minlen++;
if (minlen > buflen)
return;
#endif
/*
* The packet can contain both a mouse motion and a button event.
* In this case, the motion data comes first.
*/
if (type & HIL_MOUSEMOTION) {
flags = sc->sc_features & HIL_ABSOLUTE ?
WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y |
WSMOUSE_INPUT_ABSOLUTE_Z : WSMOUSE_INPUT_DELTA;
if (sc->sc_features & HIL_16_BITS) {
dx = *buf++;
dx |= (*buf++) << 8;
if (!(sc->sc_features & HIL_ABSOLUTE))
dx = (int16_t)dx;
} else {
dx = *buf++;
if (!(sc->sc_features & HIL_ABSOLUTE))
dx = (int8_t)dx;
}
if (sc->sc_axes > 1) {
if (sc->sc_features & HIL_16_BITS) {
dy = *buf++;
dy |= (*buf++) << 8;
if (!(sc->sc_features & HIL_ABSOLUTE))
dy = (int16_t)dy;
} else {
dy = *buf++;
if (!(sc->sc_features & HIL_ABSOLUTE))
dy = (int8_t)dy;
}
if (sc->sc_axes > 2) {
if (sc->sc_features & HIL_16_BITS) {
dz = *buf++;
dz |= (*buf++) << 8;
if (!(sc->sc_features & HIL_ABSOLUTE))
dz = (int16_t)dz;
} else {
dz = *buf++;
if (!(sc->sc_features & HIL_ABSOLUTE))
dz = (int8_t)dz;
}
} else
dz = 0;
} else
dy = dz = 0;
/*
* Correct Y direction for button boxes.
*/
if ((sc->sc_features & HIL_ABSOLUTE) == 0 &&
sc->sc_buttons == 0)
dy = -dy;
} else
dx = dy = dz = flags = 0;
if (type & HIL_MOUSEBUTTON) {
button = *buf;
/*
* The pressure sensor is very primitive and only has
* a boolean behaviour, as an extra mouse button, which is
* down if there is pressure or the pen is near the tablet,
* and up if there is no pressure or the pen is far from the
* tablet - at least for Tablet id 0x94, P/N 46088B
*
* The corresponding codes are 0x8f and 0x8e. Convert them
* to a pseudo fourth button - even if the tablet never
* has three buttons.
*/
button = (button - 0x80) >> 1;
if (button > 4)
button = 4;
if (*buf & 1) {
/* Button released, or no pressure */
sc->sc_buttonstate &= ~(1 << button);
} else {
/* Button pressed, or pressure */
sc->sc_buttonstate |= (1 << button);
}
/* buf++; */
}