#include <sys/param.h>
#include <sys/device.h>
#include <sys/systm.h>
#include <machine/autoconf.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsmousevar.h>
#include <dev/adb/adb.h>
#include <dev/adb/amsvar.h>
int amsmatch(struct device *, void *, void *);
void amsattach(struct device *, struct device *, void *);
const struct cfattach ams_ca = {
sizeof(struct ams_softc), amsmatch, amsattach
};
struct cfdriver ams_cd = {
NULL, "ams", DV_DULL
};
int ams_enable(void *);
int ams_ioctl(void *, u_long, caddr_t, int, struct proc *);
void ams_disable(void *);
const struct wsmouse_accessops ams_accessops = {
ams_enable,
ams_ioctl,
ams_disable,
};
void ems_init(struct ams_softc *);
void ms_adbcomplete(caddr_t buffer, caddr_t data_area, int adb_command);
void ms_processevent(adb_event_t *event, struct ams_softc *);
int
amsmatch(struct device *parent, void *cf, void *aux)
{
struct adb_attach_args *aa_args = aux;
if (strcmp(aa_args->name, adb_device_name) != 0)
return (0);
if (aa_args->origaddr == ADBADDR_MS)
return 1;
else
return 0;
}
void
amsattach(struct device *parent, struct device *self, void *aux)
{
ADBSetInfoBlock adbinfo;
struct ams_softc *sc = (struct ams_softc *)self;
struct adb_attach_args *aa_args = aux;
int error;
struct wsmousedev_attach_args a;
sc->origaddr = aa_args->origaddr;
sc->adbaddr = aa_args->adbaddr;
sc->handler_id = aa_args->handler_id;
sc->sc_class = MSCLASS_MOUSE;
sc->sc_buttons = 1;
sc->sc_res = 100;
sc->sc_devid[0] = 0;
sc->sc_devid[4] = 0;
adbinfo.siServiceRtPtr = (Ptr)ms_adbcomplete;
adbinfo.siDataAreaAddr = (caddr_t)sc;
ems_init(sc);
printf(": ");
switch (sc->handler_id) {
case ADBMS_200DPI:
sc->sc_res = 200;
case ADBMS_100DPI:
printf("%d-button, %d dpi mouse\n", sc->sc_buttons,
(int)(sc->sc_res));
break;
case ADBMS_MSA3:
printf("Mouse Systems A3 mouse, %d-button, %d dpi\n",
sc->sc_buttons, (int)(sc->sc_res));
break;
case ADBMS_USPEED:
printf("MicroSpeed mouse, default parameters\n");
break;
case ADBMS_UCONTOUR:
printf("Contour mouse, default parameters\n");
break;
case ADBMS_TURBO:
printf("Kensington Turbo Mouse\n");
break;
case ADBMS_EXTENDED:
if (sc->sc_devid[0] == '\0') {
printf("Logitech ");
switch (sc->sc_class) {
case MSCLASS_MOUSE:
printf("MouseMan (non-EMP) mouse");
break;
case MSCLASS_TRACKBALL:
printf("TrackMan (non-EMP) trackball");
break;
default:
printf("non-EMP relative positioning device");
break;
}
printf("\n");
} else {
printf("EMP ");
switch (sc->sc_class) {
case MSCLASS_TABLET:
printf("tablet");
break;
case MSCLASS_MOUSE:
printf("mouse");
break;
case MSCLASS_TRACKBALL:
printf("trackball");
break;
case MSCLASS_TRACKPAD:
printf("trackpad");
break;
default:
printf("unknown device");
break;
}
printf(" <%s> %d-button, %d dpi\n", sc->sc_devid,
sc->sc_buttons, (int)(sc->sc_res));
}
break;
default:
printf("relative positioning device (mouse?) (%d)\n",
sc->handler_id);
break;
}
error = set_adb_info(&adbinfo, sc->adbaddr);
#ifdef ADB_DEBUG
if (adb_debug)
printf("ams: returned %d from set_adb_info\n", error);
#endif
a.accessops = &ams_accessops;
a.accesscookie = sc;
sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
}
void
ems_init(struct ams_softc *sc)
{
int adbaddr;
short cmd;
u_char buffer[9];
adbaddr = sc->adbaddr;
if (sc->origaddr != ADBADDR_MS)
return;
if (sc->handler_id == ADBMS_USPEED ||
sc->handler_id == ADBMS_UCONTOUR) {
cmd = ADBLISTEN(adbaddr, 1);
buffer[0] = 4;
buffer[1] = 0x00;
buffer[2] = 0x00;
buffer[3] = 0x10;
buffer[4] = 0x07;
adb_op_sync((Ptr)buffer, cmd);
sc->sc_buttons = 3;
sc->sc_res = 200;
return;
}
if (sc->handler_id == ADBMS_TURBO) {
static u_char data1[] =
{ 8, 0xe7, 0x8c, 0, 0, 0, 0xff, 0xff, 0x94 };
static u_char data2[] =
{ 8, 0xa5, 0x14, 0, 0, 0x69, 0xff, 0xff, 0x27 };
buffer[0] = 0;
adb_op_sync((Ptr)buffer, ADBFLUSH(adbaddr));
adb_op_sync((Ptr)data1, ADBLISTEN(adbaddr, 2));
buffer[0] = 0;
adb_op_sync((Ptr)buffer, ADBFLUSH(adbaddr));
adb_op_sync((Ptr)data2, ADBLISTEN(adbaddr, 2));
return;
}
if ((sc->handler_id == ADBMS_100DPI) ||
(sc->handler_id == ADBMS_200DPI)) {
cmd = ADBTALK(adbaddr, 3);
if (adb_op_sync((Ptr)buffer, cmd)) {
#ifdef ADB_DEBUG
if (adb_debug)
printf("adb: ems_init timed out\n");
#endif
return;
}
buffer[2] = 4;
cmd = ADBLISTEN(adbaddr, 3);
if (adb_op_sync((Ptr)buffer, cmd)) {
#ifdef ADB_DEBUG
if (adb_debug)
printf("adb: ems_init timed out\n");
#endif
return;
}
cmd = ADBTALK(adbaddr, 3);
if (adb_op_sync((Ptr)buffer, cmd) == 0 &&
buffer[2] == ADBMS_EXTENDED) {
sc->handler_id = ADBMS_EXTENDED;
cmd = ADBTALK(adbaddr, 1);
if (adb_op_sync((Ptr)buffer, cmd)) {
#ifdef ADB_DEBUG
if (adb_debug)
printf("adb: ems_init timed out\n");
#endif
} else if (buffer[0] == 8) {
sc->sc_class = buffer[7];
sc->sc_buttons = buffer[8];
sc->sc_res = (int)*(short *)&buffer[5];
bcopy(&(buffer[1]), sc->sc_devid, 4);
} else if (buffer[1] == 0x9a &&
((buffer[2] == 0x20) || (buffer[2] == 0x21))) {
cmd = ADBLISTEN(adbaddr, 1);
buffer[0]=2;
buffer[1]=0x00;
buffer[2]=0x81;
adb_op_sync((Ptr)buffer, cmd);
cmd = ADBLISTEN(adbaddr, 1);
buffer[0]=2;
buffer[1]=0x01;
buffer[2]=0x81;
adb_op_sync((Ptr)buffer, cmd);
cmd = ADBLISTEN(adbaddr, 1);
buffer[0]=2;
buffer[1]=0x02;
buffer[2]=0x81;
adb_op_sync((Ptr)buffer, cmd);
cmd = ADBLISTEN(adbaddr, 1);
buffer[0]=2;
buffer[1]=0x03;
buffer[2]=0x38;
adb_op_sync((Ptr)buffer, cmd);
sc->sc_buttons = 3;
sc->sc_res = 400;
if (buffer[2] == 0x21)
sc->sc_class = MSCLASS_TRACKBALL;
else
sc->sc_class = MSCLASS_MOUSE;
} else
;
} else {
buffer[2] = 0x03;
cmd = ADBLISTEN(adbaddr, 3);
if (adb_op_sync((Ptr)buffer, cmd)) {
#ifdef ADB_DEBUG
if (adb_debug)
printf("adb: ems_init timed out\n");
#endif
return;
}
cmd = ADBTALK(adbaddr, 3);
if (adb_op_sync((Ptr)buffer, cmd) == 0
&& buffer[2] == ADBMS_MSA3) {
sc->handler_id = ADBMS_MSA3;
cmd = ADBLISTEN(adbaddr, 2);
buffer[0] = 3;
buffer[1] = 0x00;
buffer[2] = 0x07;
adb_op_sync((Ptr)buffer, cmd);
sc->sc_buttons = 3;
sc->sc_res = 300;
} else {
}
}
}
}
void
ms_adbcomplete(caddr_t buffer, caddr_t data_area, int adb_command)
{
adb_event_t event;
struct ams_softc *sc;
int adbaddr;
#ifdef ADB_DEBUG
int i;
if (adb_debug)
printf("adb: transaction completion\n");
#endif
adbaddr = ADB_CMDADDR(adb_command);
sc = (struct ams_softc *)data_area;
if ((sc->handler_id == ADBMS_EXTENDED) && (sc->sc_devid[0] == 0)) {
if ((buffer[3] & 0x04) == 0x04)
buffer[1] &= 0x7f;
else
buffer[1] |= 0x80;
if ((buffer[3] & 0x02) == 0x02)
buffer[2] &= 0x7f;
else
buffer[2] |= 0x80;
if ((buffer[3] & 0x01) == 0x01)
buffer[3] = 0x00;
else
buffer[3] = 0x80;
}
event.byte_count = buffer[0];
memcpy(event.bytes, buffer + 1, event.byte_count);
#ifdef ADB_DEBUG
if (adb_debug) {
printf("ams: from %d at %d (org %d) %d:", adbaddr,
sc->handler_id, sc->origaddr, buffer[0]);
for (i = 1; i <= buffer[0]; i++)
printf(" %x", buffer[i]);
printf("\n");
}
#endif
ms_processevent(&event, sc);
}
void
ms_processevent(adb_event_t *event, struct ams_softc *sc)
{
int i, button_bit, max_byte, mask;
int dx, dy, buttons;
buttons = 0;
max_byte = event->byte_count;
button_bit = 1;
switch (sc->handler_id) {
case ADBMS_USPEED:
case ADBMS_UCONTOUR:
if (max_byte == 4)
buttons = (~event->bytes[2]) & 0xff;
else
buttons = (event->bytes[0] & 0x80) ? 0 : 1;
break;
case ADBMS_MSA3:
if (max_byte == 3)
buttons = (~event->bytes[2]) & 0x07;
else
buttons = (event->bytes[0] & 0x80) ? 0 : 1;
break;
default:
for (i = 0; i < 2; i++, button_bit <<= 1)
if (!(event->bytes[i] & 0x80))
buttons |= button_bit;
else
buttons &= ~button_bit;
if (sc->sc_class == MSCLASS_MOUSE)
for (mask = 0x80; i < max_byte;
i += (mask == 0x80), button_bit <<= 1) {
if (!(event->bytes[i] & mask))
buttons |= button_bit;
else
buttons &= ~button_bit;
mask = ((mask >> 4) & 0xf)
| ((mask & 0xf) << 4);
}
break;
}
buttons |= sc->sc_mb;
dx = ((signed int) (event->bytes[1] & 0x3f)) -
((event->bytes[1] & 0x40) ? 64 : 0);
dy = ((signed int) (event->bytes[0] & 0x3f)) -
((event->bytes[0] & 0x40) ? 64 : 0);
if (sc->sc_wsmousedev)
WSMOUSE_INPUT(sc->sc_wsmousedev, buttons, dx, -dy, 0, 0);
}
int
ams_enable(void *v)
{
return 0;
}
int
ams_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
{
switch (cmd) {
case WSMOUSEIO_GTYPE:
*(u_int *)data = WSMOUSE_TYPE_ADB;
return (0);
}
return -1;
}
void
ams_disable(void *v)
{
}