2017-05-07 02:14:44 -04:00
|
|
|
/*
|
|
|
|
|
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
|
|
|
|
* running old operating systems and software designed for IBM
|
|
|
|
|
* PC systems and compatibles from 1981 through fairly recent
|
|
|
|
|
* system designs based on the PCI bus.
|
|
|
|
|
*
|
|
|
|
|
* This file is part of the 86Box distribution.
|
|
|
|
|
*
|
|
|
|
|
* Implementation of Serial Mouse devices.
|
|
|
|
|
*
|
2017-12-04 11:59:26 -05:00
|
|
|
* TODO: Add the Genius Serial Mouse.
|
2017-05-07 02:14:44 -04:00
|
|
|
*
|
2018-11-08 19:21:55 +01:00
|
|
|
* Version: @(#)mouse_serial.c 1.0.26 2018/11/05
|
2017-05-07 02:14:44 -04:00
|
|
|
*
|
|
|
|
|
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
|
|
|
|
|
*/
|
2018-05-21 19:04:05 +02:00
|
|
|
#include <stdarg.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
#include <string.h>
|
2017-05-05 01:49:42 +02:00
|
|
|
#include <stdlib.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <wchar.h>
|
2018-05-21 19:04:05 +02:00
|
|
|
#define HAVE_STDARG_H
|
2017-12-04 11:59:26 -05:00
|
|
|
#include "86box.h"
|
|
|
|
|
#include "device.h"
|
2016-06-26 00:34:39 +02:00
|
|
|
#include "timer.h"
|
2017-05-07 02:14:44 -04:00
|
|
|
#include "serial.h"
|
|
|
|
|
#include "mouse.h"
|
2017-06-17 03:31:11 -04:00
|
|
|
|
|
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
#define SERMOUSE_PORT 0 /* attach to Serial0 */
|
|
|
|
|
|
|
|
|
|
#define PHASE_IDLE 0
|
|
|
|
|
#define PHASE_ID 1
|
|
|
|
|
#define PHASE_DATA 2
|
|
|
|
|
#define PHASE_STATUS 3
|
|
|
|
|
#define PHASE_DIAGNOSTIC 4
|
|
|
|
|
#define PHASE_FORMAT_AND_REVISION 5
|
2017-12-04 11:59:26 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
const char *name; /* name of this device */
|
|
|
|
|
int8_t type, /* type of this device */
|
|
|
|
|
port;
|
2018-11-08 19:21:55 +01:00
|
|
|
uint8_t flags, but, /* device flags */
|
|
|
|
|
want_data,
|
|
|
|
|
status, format,
|
|
|
|
|
prompt, continuous,
|
|
|
|
|
id_len, id[255],
|
|
|
|
|
data_len, data[5];
|
|
|
|
|
int abs_x, abs_y;
|
2017-12-04 11:59:26 -05:00
|
|
|
|
2017-10-09 01:48:36 +02:00
|
|
|
int pos;
|
|
|
|
|
int64_t delay;
|
2018-11-08 19:21:55 +01:00
|
|
|
int64_t period;
|
2017-05-05 01:49:42 +02:00
|
|
|
int oldb;
|
2018-11-08 19:21:55 +01:00
|
|
|
int phase;
|
2017-12-04 11:59:26 -05:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
serial_t *serial;
|
2017-12-04 11:59:26 -05:00
|
|
|
} mouse_t;
|
|
|
|
|
#define FLAG_INPORT 0x80 /* device is MS InPort */
|
|
|
|
|
#define FLAG_3BTN 0x20 /* enable 3-button mode */
|
|
|
|
|
#define FLAG_SCALED 0x10 /* enable delta scaling */
|
|
|
|
|
#define FLAG_INTR 0x04 /* dev can send interrupts */
|
|
|
|
|
#define FLAG_FROZEN 0x02 /* do not update counters */
|
|
|
|
|
#define FLAG_ENABLED 0x01 /* dev is enabled for use */
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-05 01:49:42 +02:00
|
|
|
|
2018-05-21 19:04:05 +02:00
|
|
|
#ifdef ENABLE_MOUSE_SERIAL_LOG
|
|
|
|
|
int mouse_serial_do_log = ENABLE_MOUSE_SERIAL_LOG;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2018-10-19 00:39:32 +02:00
|
|
|
mouse_serial_log(const char *fmt, ...)
|
2018-05-21 19:04:05 +02:00
|
|
|
{
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
|
if (mouse_serial_do_log) {
|
2018-10-19 00:39:32 +02:00
|
|
|
va_start(ap, fmt);
|
|
|
|
|
pclog_ex(fmt, ap);
|
2018-05-21 19:04:05 +02:00
|
|
|
va_end(ap);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-10-19 00:39:32 +02:00
|
|
|
#else
|
|
|
|
|
#define mouse_serial_log(fmt, ...)
|
|
|
|
|
#endif
|
2018-05-21 19:04:05 +02:00
|
|
|
|
|
|
|
|
|
2017-05-07 02:14:44 -04:00
|
|
|
/* Callback from serial driver: RTS was toggled. */
|
2017-05-05 01:49:42 +02:00
|
|
|
static void
|
2018-11-08 19:21:55 +01:00
|
|
|
sermouse_callback(struct serial_s *serial, void *priv)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-12-04 11:59:26 -05:00
|
|
|
mouse_t *dev = (mouse_t *)priv;
|
2017-05-07 02:14:44 -04:00
|
|
|
|
|
|
|
|
/* Start a timer to wake us up in a little while. */
|
2018-11-08 19:21:55 +01:00
|
|
|
dev->pos = 0;
|
|
|
|
|
dev->phase = PHASE_ID;
|
|
|
|
|
dev->delay = dev->period;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-05-05 01:49:42 +02:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
static uint8_t
|
|
|
|
|
sermouse_data_msystems(mouse_t *dev, int x, int y, int b)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2018-11-08 19:21:55 +01:00
|
|
|
dev->data[0] = 0x80;
|
|
|
|
|
dev->data[0] |= (b & 0x01) ? 0x00 : 0x04; /* left button */
|
|
|
|
|
dev->data[0] |= (b & 0x02) ? 0x00 : 0x01; /* middle button */
|
|
|
|
|
dev->data[0] |= (b & 0x04) ? 0x00 : 0x02; /* right button */
|
|
|
|
|
dev->data[1] = x;
|
|
|
|
|
dev->data[2] = -y;
|
|
|
|
|
dev->data[3] = x; /* same as byte 1 */
|
|
|
|
|
dev->data[4] = -y; /* same as byte 2 */
|
|
|
|
|
|
|
|
|
|
return 5;
|
|
|
|
|
}
|
2017-05-05 01:49:42 +02:00
|
|
|
|
2017-05-07 02:14:44 -04:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
static uint8_t
|
|
|
|
|
sermouse_data_3bp(mouse_t *dev, int x, int y, int b)
|
|
|
|
|
{
|
|
|
|
|
dev->data[0] |= (b & 0x01) ? 0x00 : 0x04; /* left button */
|
|
|
|
|
dev->data[0] |= (b & 0x02) ? 0x00 : 0x02; /* middle button */
|
|
|
|
|
dev->data[0] |= (b & 0x04) ? 0x00 : 0x01; /* right button */
|
|
|
|
|
dev->data[1] = x;
|
|
|
|
|
dev->data[2] = -y;
|
|
|
|
|
|
|
|
|
|
return 3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint8_t
|
|
|
|
|
sermouse_data_mmseries(mouse_t *dev, int x, int y, int b)
|
|
|
|
|
{
|
|
|
|
|
if (x < -127)
|
|
|
|
|
x = -127;
|
|
|
|
|
if (y < -127)
|
|
|
|
|
y = -127;
|
|
|
|
|
|
|
|
|
|
dev->data[0] = 0x80;
|
|
|
|
|
if (x >= 0)
|
|
|
|
|
dev->data[0] |= 0x10;
|
|
|
|
|
if (y < 0)
|
|
|
|
|
dev->data[0] |= 0x08;
|
|
|
|
|
dev->data[0] |= (b & 0x01) ? 0x04 : 0x00; /* left button */
|
|
|
|
|
dev->data[0] |= (b & 0x02) ? 0x02 : 0x00; /* middle button */
|
|
|
|
|
dev->data[0] |= (b & 0x04) ? 0x01 : 0x00; /* right button */
|
|
|
|
|
dev->data[1] = abs(x);
|
|
|
|
|
dev->data[2] = abs(y);
|
|
|
|
|
|
|
|
|
|
return 3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint8_t
|
|
|
|
|
sermouse_data_bp1(mouse_t *dev, int x, int y, int b)
|
|
|
|
|
{
|
|
|
|
|
dev->data[0] = 0x80;
|
|
|
|
|
dev->data[0] |= (b & 0x01) ? 0x10 : 0x00; /* left button */
|
|
|
|
|
dev->data[0] |= (b & 0x02) ? 0x08 : 0x00; /* middle button */
|
|
|
|
|
dev->data[0] |= (b & 0x04) ? 0x04 : 0x00; /* right button */
|
|
|
|
|
dev->data[1] = (x & 0x3f);
|
|
|
|
|
dev->data[2] = (x >> 6);
|
|
|
|
|
dev->data[3] = (y & 0x3f);
|
|
|
|
|
dev->data[4] = (y >> 6);
|
|
|
|
|
|
|
|
|
|
return 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint8_t
|
|
|
|
|
sermouse_data_ms(mouse_t *dev, int x, int y, int z, int b)
|
|
|
|
|
{
|
|
|
|
|
uint8_t len;
|
|
|
|
|
|
|
|
|
|
dev->data[0] = 0x40;
|
|
|
|
|
dev->data[0] |= (((y >> 6) & 0x03) << 2);
|
|
|
|
|
dev->data[0] |= ((x >> 6) & 0x03);
|
|
|
|
|
if (b & 0x01)
|
|
|
|
|
dev->data[0] |= 0x20;
|
|
|
|
|
if (b & 0x02)
|
|
|
|
|
dev->data[0] |= 0x10;
|
|
|
|
|
dev->data[1] = x & 0x3F;
|
|
|
|
|
dev->data[2] = y & 0x3F;
|
|
|
|
|
if (dev->but == 3) {
|
|
|
|
|
len = 3;
|
|
|
|
|
if (dev->type == MOUSE_TYPE_LT3BUTTON) {
|
|
|
|
|
if (b & 0x04) {
|
|
|
|
|
dev->data[3] = 0x20;
|
|
|
|
|
len++;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if ((b ^ dev->oldb) & 0x04) {
|
|
|
|
|
/* Microsoft 3-button mice send a fourth byte of 0x00 when the middle button
|
|
|
|
|
has changed. */
|
|
|
|
|
dev->data[3] = 0x00;
|
|
|
|
|
len++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (dev->but == 4) {
|
|
|
|
|
len = 4;
|
|
|
|
|
dev->data[3] = z & 0x0F;
|
|
|
|
|
if (b & 0x04)
|
|
|
|
|
dev->data[3] |= 0x10;
|
|
|
|
|
} else
|
|
|
|
|
len = 3;
|
|
|
|
|
|
|
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint8_t
|
|
|
|
|
sermouse_data_hex(mouse_t *dev, int x, int y, int b)
|
|
|
|
|
{
|
|
|
|
|
char ret[6] = { 0, 0, 0, 0, 0, 0 };
|
|
|
|
|
uint8_t i, but = 0x00;
|
|
|
|
|
|
|
|
|
|
but |= (b & 0x01) ? 0x04 : 0x00; /* left button */
|
|
|
|
|
but |= (b & 0x02) ? 0x02 : 0x00; /* middle button */
|
|
|
|
|
but |= (b & 0x04) ? 0x01 : 0x00; /* right button */
|
|
|
|
|
|
|
|
|
|
sprintf(ret, "%02X%02X%01X", (int8_t) y, (int8_t) x, but & 0x0f);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 5; i++)
|
|
|
|
|
dev->data[i] = ret[4 - i];
|
|
|
|
|
|
|
|
|
|
return 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
sermouse_report(int x, int y, int z, int b, mouse_t *dev)
|
|
|
|
|
{
|
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
|
|
memset(dev->data, 0, 5);
|
2017-08-03 14:07:03 -04:00
|
|
|
|
2017-12-10 02:08:37 -05:00
|
|
|
switch(dev->type) {
|
2017-08-03 14:07:03 -04:00
|
|
|
case MOUSE_TYPE_MSYSTEMS:
|
2018-11-08 19:21:55 +01:00
|
|
|
len = sermouse_data_msystems(dev, x, y, b);
|
2017-08-03 14:07:03 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MOUSE_TYPE_MICROSOFT:
|
2018-11-08 19:21:55 +01:00
|
|
|
case MOUSE_TYPE_MS3BUTTON:
|
|
|
|
|
case MOUSE_TYPE_MSWHEEL:
|
|
|
|
|
len = sermouse_data_ms(dev, x, y, z, b);
|
2017-06-21 19:45:15 +02:00
|
|
|
break;
|
|
|
|
|
|
2017-08-03 14:07:03 -04:00
|
|
|
case MOUSE_TYPE_LOGITECH:
|
2018-11-08 19:21:55 +01:00
|
|
|
case MOUSE_TYPE_LT3BUTTON:
|
|
|
|
|
switch (dev->format) {
|
|
|
|
|
case 0:
|
|
|
|
|
len = sermouse_data_msystems(dev, x, y, b);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
len = sermouse_data_3bp(dev, x, y, b);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
len = sermouse_data_hex(dev, x, y, b);
|
|
|
|
|
break;
|
|
|
|
|
case 3: /* Relative */
|
|
|
|
|
len = sermouse_data_bp1(dev, x, y, b);
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
len = sermouse_data_mmseries(dev, x, y, b);
|
|
|
|
|
break;
|
|
|
|
|
case 6: /* Absolute */
|
|
|
|
|
len = sermouse_data_bp1(dev, dev->abs_x, dev->abs_y, b);
|
|
|
|
|
break;
|
|
|
|
|
case 7:
|
|
|
|
|
len = sermouse_data_ms(dev, x, y, z, b);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2017-06-21 19:45:15 +02:00
|
|
|
break;
|
2018-11-08 19:21:55 +01:00
|
|
|
}
|
2017-06-21 19:45:15 +02:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
dev->oldb = b;
|
|
|
|
|
dev->data_len = len;
|
|
|
|
|
|
|
|
|
|
dev->pos = 0;
|
|
|
|
|
|
|
|
|
|
if (dev->phase != PHASE_DATA)
|
|
|
|
|
dev->phase = PHASE_DATA;
|
|
|
|
|
|
|
|
|
|
if (!dev->delay)
|
|
|
|
|
dev->delay = dev->period;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Callback timer expired, now send our "mouse ID" to the serial port. */
|
|
|
|
|
static void
|
|
|
|
|
sermouse_timer(void *priv)
|
|
|
|
|
{
|
|
|
|
|
mouse_t *dev = (mouse_t *)priv;
|
2017-12-04 11:59:26 -05:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
switch (dev->phase) {
|
|
|
|
|
case PHASE_ID:
|
|
|
|
|
serial_write_fifo(dev->serial, dev->id[dev->pos]);
|
|
|
|
|
dev->pos++;
|
|
|
|
|
if (dev->pos == dev->id_len) {
|
|
|
|
|
dev->delay = 0LL;
|
|
|
|
|
dev->pos = 0;
|
|
|
|
|
dev->phase = PHASE_IDLE;
|
|
|
|
|
} else
|
|
|
|
|
dev->delay += dev->period;
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_DATA:
|
|
|
|
|
serial_write_fifo(dev->serial, dev->data[dev->pos]);
|
|
|
|
|
dev->pos++;
|
|
|
|
|
if (dev->pos == dev->data_len) {
|
|
|
|
|
dev->delay = 0LL;
|
|
|
|
|
dev->pos = 0;
|
|
|
|
|
dev->phase = PHASE_IDLE;
|
|
|
|
|
} else
|
|
|
|
|
dev->delay += dev->period;
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_STATUS:
|
|
|
|
|
serial_write_fifo(dev->serial, dev->status);
|
|
|
|
|
dev->delay = 0LL;
|
|
|
|
|
dev->pos = 0;
|
|
|
|
|
dev->phase = PHASE_IDLE;
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_DIAGNOSTIC:
|
|
|
|
|
if (dev->pos)
|
|
|
|
|
serial_write_fifo(dev->serial, 0x00);
|
|
|
|
|
else /* This should return the last button status, bits 2,1,0 = L,M,R. */
|
|
|
|
|
serial_write_fifo(dev->serial, 0x00);
|
|
|
|
|
dev->pos++;
|
|
|
|
|
if (dev->pos == 3) {
|
|
|
|
|
dev->delay = 0LL;
|
|
|
|
|
dev->pos = 0;
|
|
|
|
|
dev->phase = PHASE_IDLE;
|
|
|
|
|
} else
|
|
|
|
|
dev->delay += dev->period;
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_FORMAT_AND_REVISION:
|
|
|
|
|
serial_write_fifo(dev->serial, 0x10 | (dev->format << 1));
|
|
|
|
|
dev->delay = 0LL;
|
|
|
|
|
dev->pos = 0;
|
|
|
|
|
dev->phase = PHASE_IDLE;
|
|
|
|
|
break;
|
2017-12-04 11:59:26 -05:00
|
|
|
default:
|
2018-11-08 19:21:55 +01:00
|
|
|
dev->delay = 0LL;
|
|
|
|
|
dev->pos = 0;
|
|
|
|
|
dev->phase = PHASE_IDLE;
|
|
|
|
|
break;
|
2017-05-05 01:49:42 +02:00
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2017-05-05 01:49:42 +02:00
|
|
|
|
|
|
|
|
|
2017-12-04 11:59:26 -05:00
|
|
|
static int
|
2017-05-05 01:49:42 +02:00
|
|
|
sermouse_poll(int x, int y, int z, int b, void *priv)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-12-04 11:59:26 -05:00
|
|
|
mouse_t *dev = (mouse_t *)priv;
|
2017-05-05 01:49:42 +02:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
if (!x && !y && (b == dev->oldb) && dev->continuous)
|
|
|
|
|
return(1);
|
2017-05-05 01:49:42 +02:00
|
|
|
|
2017-12-04 11:59:26 -05:00
|
|
|
dev->oldb = b;
|
2018-11-08 19:21:55 +01:00
|
|
|
dev->abs_x += x;
|
|
|
|
|
dev->abs_y += y;
|
|
|
|
|
if (dev->abs_x < 0)
|
|
|
|
|
dev->abs_x = 0;
|
|
|
|
|
if (dev->abs_x > 4095)
|
|
|
|
|
dev->abs_x = 4095;
|
|
|
|
|
if (dev->abs_y < 0)
|
|
|
|
|
dev->abs_y = 0;
|
|
|
|
|
if (dev->abs_y > 4095)
|
|
|
|
|
dev->abs_y = 4095;
|
|
|
|
|
|
|
|
|
|
if (dev->format == 3) {
|
|
|
|
|
if (x > 2047) x = 2047;
|
|
|
|
|
if (y > 2047) y = 2047;
|
|
|
|
|
if (x <- 2048) x = -2048;
|
|
|
|
|
if (y <- 2048) y = -2048;
|
|
|
|
|
} else {
|
|
|
|
|
if (x > 127) x = 127;
|
|
|
|
|
if (y > 127) y = 127;
|
|
|
|
|
if (x <- 128) x = -128;
|
|
|
|
|
if (y <- 128) y = -128;
|
|
|
|
|
}
|
2017-06-17 03:31:11 -04:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
/* No report if we're either in prompt mode,
|
|
|
|
|
or the mouse wants data. */
|
|
|
|
|
if (!dev->prompt && !dev->want_data)
|
|
|
|
|
sermouse_report(x, y, z, b, dev);
|
2017-05-05 01:49:42 +02:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
return(0);
|
|
|
|
|
}
|
2017-06-17 03:31:11 -04:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ltsermouse_write(struct serial_s *serial, void *priv, uint8_t data)
|
|
|
|
|
{
|
|
|
|
|
mouse_t *dev = (mouse_t *)priv;
|
2017-05-07 02:14:44 -04:00
|
|
|
|
2017-05-05 01:49:42 +02:00
|
|
|
#if 0
|
2018-11-08 19:21:55 +01:00
|
|
|
/* Make sure to stop any transmission when we receive a byte. */
|
|
|
|
|
if (dev->phase != PHASE_IDLE) {
|
|
|
|
|
dev->delay = 0LL;
|
|
|
|
|
dev->phase = PHASE_IDLE;
|
|
|
|
|
}
|
2017-05-05 01:49:42 +02:00
|
|
|
#endif
|
2017-06-17 07:23:49 +02:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
if (dev->want_data) switch (dev->want_data) {
|
|
|
|
|
case 0x2A:
|
|
|
|
|
dev->data_len--;
|
|
|
|
|
dev->want_data = 0;
|
|
|
|
|
dev->delay = 0LL;
|
|
|
|
|
dev->phase = PHASE_IDLE;
|
|
|
|
|
switch (data) {
|
|
|
|
|
default:
|
|
|
|
|
mouse_serial_log("Serial mouse: Invalid period %02X, using 1200 bps\n", data);
|
|
|
|
|
case 0x6E:
|
|
|
|
|
dev->period = 7500LL; /* 1200 bps */
|
|
|
|
|
break;
|
|
|
|
|
case 0x6F:
|
|
|
|
|
dev->period = 3750LL; /* 2400 bps */
|
|
|
|
|
break;
|
|
|
|
|
case 0x70:
|
|
|
|
|
dev->period = 1875LL; /* 4800 bps */
|
|
|
|
|
break;
|
|
|
|
|
case 0x71:
|
|
|
|
|
dev->period = 938LL; /* 9600 bps */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
dev->period *= TIMER_USEC;
|
|
|
|
|
break;
|
|
|
|
|
} else switch (data) {
|
|
|
|
|
case 0x2A:
|
|
|
|
|
dev->want_data = data;
|
|
|
|
|
dev->data_len = 1;
|
|
|
|
|
break;
|
|
|
|
|
case 0x44: /* Set prompt mode */
|
|
|
|
|
dev->prompt = 1;
|
|
|
|
|
dev->status |= 0x40;
|
|
|
|
|
break;
|
|
|
|
|
case 0x50:
|
|
|
|
|
if (!dev->prompt) {
|
|
|
|
|
dev->prompt = 1;
|
|
|
|
|
dev->status |= 0x40;
|
|
|
|
|
}
|
|
|
|
|
/* TODO: Here we should send the current position. */
|
|
|
|
|
break;
|
|
|
|
|
case 0x73: /* Status */
|
|
|
|
|
dev->pos = 0;
|
|
|
|
|
dev->phase = PHASE_STATUS;
|
|
|
|
|
if (!dev->delay)
|
|
|
|
|
dev->delay = dev->period;
|
|
|
|
|
break;
|
|
|
|
|
case 0x4A: /* Report Rate Selection commands */
|
|
|
|
|
case 0x4B:
|
|
|
|
|
case 0x4C:
|
|
|
|
|
case 0x52:
|
|
|
|
|
case 0x4D:
|
|
|
|
|
case 0x51:
|
|
|
|
|
case 0x4E:
|
|
|
|
|
case 0x4F:
|
|
|
|
|
dev->prompt = 0;
|
|
|
|
|
dev->status &= 0xBF;
|
|
|
|
|
// dev->continuous = (data == 0x4F);
|
|
|
|
|
break;
|
|
|
|
|
case 0x41:
|
|
|
|
|
dev->format = 6; /* Aboslute Bit Pad One Format */
|
|
|
|
|
dev->abs_x = dev->abs_y = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x42:
|
|
|
|
|
dev->format = 3; /* Relative Bit Pad One Format */
|
|
|
|
|
break;
|
|
|
|
|
case 0x53:
|
|
|
|
|
dev->format = 5; /* MM Series Format */
|
|
|
|
|
break;
|
|
|
|
|
case 0x54:
|
|
|
|
|
dev->format = 1; /* Three Byte Packed Binary Format */
|
|
|
|
|
break;
|
|
|
|
|
case 0x55: /* This is the Mouse Systems-compatible format */
|
|
|
|
|
dev->format = 0; /* Five Byte Packed Binary Format */
|
|
|
|
|
break;
|
|
|
|
|
case 0x56:
|
|
|
|
|
dev->format = 7; /* Microsoft Compatible Format */
|
|
|
|
|
break;
|
|
|
|
|
case 0x57:
|
|
|
|
|
dev->format = 2; /* Hexadecimal Format */
|
|
|
|
|
break;
|
|
|
|
|
case 0x05:
|
|
|
|
|
dev->pos = 0;
|
|
|
|
|
dev->phase = PHASE_DIAGNOSTIC;
|
|
|
|
|
if (!dev->delay)
|
|
|
|
|
dev->delay = dev->period;
|
|
|
|
|
break;
|
|
|
|
|
case 0x66:
|
|
|
|
|
dev->pos = 0;
|
|
|
|
|
dev->phase = PHASE_FORMAT_AND_REVISION;
|
|
|
|
|
if (!dev->delay)
|
|
|
|
|
dev->delay = dev->period;
|
|
|
|
|
break;
|
2017-12-05 13:37:06 -05:00
|
|
|
}
|
2017-06-17 07:23:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-05-05 01:49:42 +02:00
|
|
|
static void
|
|
|
|
|
sermouse_close(void *priv)
|
2016-12-23 03:16:24 +01:00
|
|
|
{
|
2017-12-04 11:59:26 -05:00
|
|
|
mouse_t *dev = (mouse_t *)priv;
|
2017-05-05 01:49:42 +02:00
|
|
|
|
|
|
|
|
/* Detach serial port from the mouse. */
|
2018-11-08 19:21:55 +01:00
|
|
|
if (dev && dev->serial && dev->serial->sd)
|
|
|
|
|
memset(dev->serial->sd, 0, sizeof(serial_device_t));
|
2017-05-05 01:49:42 +02:00
|
|
|
|
2017-12-04 11:59:26 -05:00
|
|
|
free(dev);
|
2016-12-23 03:16:24 +01:00
|
|
|
}
|
|
|
|
|
|
2017-05-05 01:49:42 +02:00
|
|
|
|
2017-12-04 11:59:26 -05:00
|
|
|
/* Initialize the device for use by the user. */
|
2017-05-29 01:18:32 +02:00
|
|
|
static void *
|
2018-03-19 01:02:04 +01:00
|
|
|
sermouse_init(const device_t *info)
|
2017-05-29 01:18:32 +02:00
|
|
|
{
|
2017-12-04 11:59:26 -05:00
|
|
|
mouse_t *dev;
|
|
|
|
|
|
|
|
|
|
dev = (mouse_t *)malloc(sizeof(mouse_t));
|
|
|
|
|
memset(dev, 0x00, sizeof(mouse_t));
|
|
|
|
|
dev->name = info->name;
|
2018-11-08 19:21:55 +01:00
|
|
|
dev->but = device_get_config_int("buttons");
|
|
|
|
|
dev->continuous = 1;
|
|
|
|
|
if (dev->but > 2)
|
2017-12-10 02:08:37 -05:00
|
|
|
dev->flags |= FLAG_3BTN;
|
2017-06-17 03:31:11 -04:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
if (info->local == MOUSE_TYPE_MSYSTEMS) {
|
|
|
|
|
dev->period = 8333LL * TIMER_USEC; /* 1200 bps, 8 data bits, 1 start bit, 1 stop bit, no parity bit */
|
2018-01-26 13:50:09 +01:00
|
|
|
dev->type = info->local;
|
2018-11-08 19:21:55 +01:00
|
|
|
dev->id_len = 1;
|
|
|
|
|
dev->id[0] = 'H';
|
|
|
|
|
} else {
|
|
|
|
|
dev->format = 7;
|
|
|
|
|
dev->status = 0x0f;
|
|
|
|
|
dev->period = 7500LL * TIMER_USEC; /* 1200 bps, 7 data bits, 1 start bit, 1 stop bit, no parity bit */
|
|
|
|
|
dev->id_len = 1;
|
|
|
|
|
dev->id[0] = 'M';
|
|
|
|
|
switch(dev->but) {
|
2018-01-26 13:50:09 +01:00
|
|
|
case 2:
|
|
|
|
|
default:
|
2018-11-08 19:21:55 +01:00
|
|
|
dev->type = info->local ? MOUSE_TYPE_LOGITECH : MOUSE_TYPE_MICROSOFT;
|
2018-01-26 13:50:09 +01:00
|
|
|
break;
|
|
|
|
|
case 3:
|
2018-11-08 19:21:55 +01:00
|
|
|
dev->type = info->local ? MOUSE_TYPE_LT3BUTTON : MOUSE_TYPE_MS3BUTTON;
|
|
|
|
|
dev->id_len = 2;
|
|
|
|
|
dev->id[1] = '3';
|
2018-01-26 13:50:09 +01:00
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
dev->type = MOUSE_TYPE_MSWHEEL;
|
2018-11-08 19:21:55 +01:00
|
|
|
dev->id_len = 6;
|
|
|
|
|
dev->id[1] = 'Z';
|
|
|
|
|
dev->id[2] = '@';
|
2018-01-26 13:50:09 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dev->port = device_get_config_int("port");
|
|
|
|
|
|
2017-05-29 01:18:32 +02:00
|
|
|
/* Attach a serial port to the mouse. */
|
2018-11-08 19:21:55 +01:00
|
|
|
if (info->local)
|
|
|
|
|
dev->serial = serial_attach(dev->port, sermouse_callback, ltsermouse_write, dev);
|
|
|
|
|
else
|
|
|
|
|
dev->serial = serial_attach(dev->port, sermouse_callback, NULL, dev);
|
2017-12-04 11:59:26 -05:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
mouse_serial_log("%s: port=COM%d\n", dev->name, dev->port + 1);
|
2017-05-29 01:18:32 +02:00
|
|
|
|
2017-12-04 11:59:26 -05:00
|
|
|
timer_add(sermouse_timer, &dev->delay, &dev->delay, dev);
|
2017-05-29 01:18:32 +02:00
|
|
|
|
2017-12-10 02:08:37 -05:00
|
|
|
/* Tell them how many buttons we have. */
|
|
|
|
|
mouse_set_buttons((dev->flags & FLAG_3BTN) ? 3 : 2);
|
|
|
|
|
|
2017-12-04 11:59:26 -05:00
|
|
|
/* Return our private data to the I/O layer. */
|
|
|
|
|
return(dev);
|
2017-05-29 01:18:32 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-17 03:31:11 -04:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
static const device_config_t mssermouse_config[] = {
|
2017-12-04 11:59:26 -05:00
|
|
|
{
|
2017-12-10 02:08:37 -05:00
|
|
|
"port", "Serial Port", CONFIG_SELECTION, "", 0, {
|
2017-12-04 11:59:26 -05:00
|
|
|
{
|
2017-12-10 02:08:37 -05:00
|
|
|
"COM1", 0
|
2017-12-04 11:59:26 -05:00
|
|
|
},
|
|
|
|
|
{
|
2017-12-10 02:08:37 -05:00
|
|
|
"COM2", 1
|
2017-12-04 11:59:26 -05:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
""
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
2017-12-10 02:08:37 -05:00
|
|
|
"buttons", "Buttons", CONFIG_SELECTION, "", 2, {
|
2017-12-04 11:59:26 -05:00
|
|
|
{
|
2017-12-10 02:08:37 -05:00
|
|
|
"Two", 2
|
2017-12-04 11:59:26 -05:00
|
|
|
},
|
|
|
|
|
{
|
2017-12-10 02:08:37 -05:00
|
|
|
"Three", 3
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"Wheel", 4
|
2017-12-04 11:59:26 -05:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
""
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"", "", -1
|
|
|
|
|
}
|
2017-06-17 03:31:11 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
static const device_config_t ltsermouse_config[] = {
|
|
|
|
|
{
|
|
|
|
|
"port", "Serial Port", CONFIG_SELECTION, "", 0, {
|
|
|
|
|
{
|
|
|
|
|
"COM1", 0
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"COM2", 1
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
""
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"buttons", "Buttons", CONFIG_SELECTION, "", 2, {
|
|
|
|
|
{
|
|
|
|
|
"Two", 2
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"Three", 3
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
""
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"", "", -1
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2018-03-19 01:02:04 +01:00
|
|
|
const device_t mouse_mssystems_device = {
|
2017-12-04 11:59:26 -05:00
|
|
|
"Mouse Systems Serial Mouse",
|
|
|
|
|
0,
|
2017-12-10 02:08:37 -05:00
|
|
|
MOUSE_TYPE_MSYSTEMS,
|
2017-12-04 11:59:26 -05:00
|
|
|
sermouse_init, sermouse_close, NULL,
|
2018-04-26 13:33:29 +02:00
|
|
|
sermouse_poll, NULL, NULL,
|
2018-11-08 19:21:55 +01:00
|
|
|
mssermouse_config
|
2017-06-17 03:31:11 -04:00
|
|
|
};
|
2017-06-19 06:46:08 +02:00
|
|
|
|
2018-03-19 01:02:04 +01:00
|
|
|
const device_t mouse_msserial_device = {
|
2018-11-08 19:21:55 +01:00
|
|
|
"Microsoft Serial Mouse",
|
|
|
|
|
0,
|
2017-12-04 11:59:26 -05:00
|
|
|
0,
|
2018-11-08 19:21:55 +01:00
|
|
|
sermouse_init, sermouse_close, NULL,
|
|
|
|
|
sermouse_poll, NULL, NULL,
|
|
|
|
|
mssermouse_config
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const device_t mouse_ltserial_device = {
|
|
|
|
|
"Logitech Serial Mouse",
|
2017-12-04 11:59:26 -05:00
|
|
|
0,
|
2018-11-08 19:21:55 +01:00
|
|
|
1,
|
2017-12-04 11:59:26 -05:00
|
|
|
sermouse_init, sermouse_close, NULL,
|
2018-04-26 13:33:29 +02:00
|
|
|
sermouse_poll, NULL, NULL,
|
2018-11-08 19:21:55 +01:00
|
|
|
ltsermouse_config
|
2017-07-18 14:55:09 +02:00
|
|
|
};
|