From 9d1175d1d881cf70fee03465d9dedf74eb5fa8da Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 2 Mar 2023 16:45:47 +0600 Subject: [PATCH 1/3] Prepare for ArtPad emulation --- src/device/mouse_wacom_tablet.c | 223 ++++++++++++++++++++++++++------ 1 file changed, 187 insertions(+), 36 deletions(-) diff --git a/src/device/mouse_wacom_tablet.c b/src/device/mouse_wacom_tablet.c index f6f39fa95..ea15d7f12 100644 --- a/src/device/mouse_wacom_tablet.c +++ b/src/device/mouse_wacom_tablet.c @@ -19,17 +19,43 @@ enum wacom_modes { WACOM_MODE_SWITCH = 3, }; +enum wacom_handshake_modes { + WACOM_HANDSHAKE_NONE = 0, + WACOM_HANDSHAKE_CTS = 1, + WACOM_HANDSHAKE_DTS = 2, + WACOM_HANDSHAKE_BOTH = 3, +}; + +enum wacom_cmd_set { + WACOM_CMDSET_BITPAD = 0, + WACOM_CMDSET_MM1201 = 1, + WACOM_CMDSET_IIS = 2, + WACOM_CMDSET_IV = 3 +}; + enum { REPORT_PHASE_PREPARE, REPORT_PHASE_TRANSMIT }; +typedef struct wacom_tablet_id { + char id[512]; +} wacom_tablet_id; + +static const wacom_tablet_id sd510_id = { + .id = "~#SD51C V3.2.1.01\r" +}; + +static const wacom_tablet_id artpad_id = { + .id = "~#KT-0405-R00 V1.1-0\r" +}; + typedef struct { const char *name; /* name of this device */ int8_t type, /* type of this device */ port; uint8_t flags, but, /* device flags */ - status, format, + status, bits, data_len, data[64], data_rec[0x200]; int abs_x, abs_y, @@ -42,11 +68,44 @@ typedef struct { int reset; int transmit_id, transmit_id_pending; int pressure_mode; - int suppressed, measurement, always_report; - int remote_req, remote_mode; + int suppressed, measurement; + int remote_req; - int last_abs_x, last_abs_y; /* Suppressed/Increment Mode. */ - uint32_t settings; /* Settings DWORD */ + int last_abs_x, last_abs_y; /* Suppressed/Increment Mode. */ + union { + uint32_t settings; /* Settings DWORD */ + /* We don't target any architectures except x86/x64/ARM32/ARM64. + (The ABIs for those are explicit in little-endian bit ordering) */ + struct { + uint8_t remote_mode : 1; + uint8_t bitpad_two_cursor_data : 1; + uint8_t mm961_orientation : 1; + uint8_t mm_command_set : 1; + uint8_t tilt : 1; + uint8_t multi_device : 1; + uint8_t reading_height : 1; + uint8_t pressure_sensitivity : 1; + + uint8_t pnp : 1; /* Unused. */ + uint8_t dummy : 1; + uint8_t terminator : 2; + uint8_t out_of_range_data : 1; + uint8_t origin_location : 1; + uint8_t resolution : 2; + + uint8_t transfer_rate : 2; + uint8_t coord_sys : 1; + uint8_t output_format : 1; + uint8_t transfer_mode : 2; + uint8_t handshake : 2; + + uint8_t stop_bits_conf : 1; + uint8_t data_bits_conf : 1; + uint8_t parity : 2; + uint8_t baud_rate : 2; + uint8_t cmd_set : 2; + } settings_bits; + }; double transmit_period; double old_tsc, reset_tsc; @@ -55,12 +114,22 @@ typedef struct { serial_t *serial; } mouse_wacom_t; +static unsigned int +reverse(register unsigned int x) +{ + x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); + x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); + x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); + x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); + return ((x >> 16) | (x << 16)); +} + static double wacom_transmit_period(mouse_wacom_t *dev, int bps, int rps) { double dbps = (double) bps; double temp = 0.0; - int word_len = 10; + int word_len = dev->bits; if (rps == -1) temp = (double) word_len; @@ -74,25 +143,85 @@ wacom_transmit_period(mouse_wacom_t *dev, int bps, int rps) return temp; } +static void +wacom_process_settings_dword(mouse_wacom_t *wacom, uint32_t dword) +{ + wacom->settings = dword; + + wacom->mode = wacom->settings_bits.transfer_mode; + + wacom->bits = 7 + wacom->settings_bits.data_bits_conf; + wacom->bits += 1 + wacom->settings_bits.stop_bits_conf; + if (wacom->settings_bits.parity == 2 && !(wacom->bits % 2)) { + wacom->bits++; + } else if (wacom->settings_bits.parity == 3 && (wacom->bits % 2)) { + wacom->bits++; + } + + switch(wacom->settings_bits.baud_rate) { + case 0: + wacom->transmit_period = wacom_transmit_period(wacom, 2400, -1); + break; + + case 1: + wacom->transmit_period = wacom_transmit_period(wacom, 4800, -1); + break; + + case 2: + wacom->transmit_period = wacom_transmit_period(wacom, 9600, -1); + break; + + case 3: + wacom->transmit_period = wacom_transmit_period(wacom, 19200, -1); + break; + } + + mouse_mode = !wacom->settings_bits.coord_sys; +} + static void wacom_reset(mouse_wacom_t *wacom) { - wacom->transmit_period = wacom_transmit_period(wacom, 9600, -1); - wacom->mode = WACOM_MODE_POINT; - wacom->data_pos = 0; - wacom->transmission_ongoing = 0; - wacom->mode = 0; - wacom->transmission_stopped = 0; - wacom->interval = 0; - wacom->transmit_id = 0; - wacom->format = 0; /* ASCII */ - wacom->measurement = 1; + wacom->transmit_period = wacom_transmit_period(wacom, 9600, -1); + wacom->mode = WACOM_MODE_POINT; + wacom->data_pos = 0; + wacom->transmission_ongoing = 0; + wacom->transmission_stopped = 0; + wacom->interval = 0; + wacom->transmit_id = 0; + wacom->settings_bits.output_format = 1; /* ASCII */ + wacom->settings_bits.cmd_set = 1; + wacom->measurement = 1; wacom->increment = wacom->suppressed_increment = 0; wacom->reset_tsc = tsc; - wacom->remote_mode = wacom->remote_req = 0; - wacom->always_report = 0; + wacom->settings_bits.remote_mode = wacom->remote_req = 0; + wacom->settings_bits.out_of_range_data = 0; mouse_mode = 1; + wacom_process_settings_dword(wacom, 0xA21BC800); +} + +static void +wacom_reset_artpad(mouse_wacom_t *wacom) +{ + wacom->transmit_period = wacom_transmit_period(wacom, 9600, -1); + wacom->mode = WACOM_MODE_SUPPRESSED; + wacom->data_pos = 0; + wacom->transmission_ongoing = 0; + wacom->transmission_stopped = 0; + wacom->interval = 0; + wacom->transmit_id = 0; + wacom->settings_bits.output_format = 0; /* Binary */ + wacom->measurement = 1; + wacom->increment = 0; + wacom->suppressed_increment = 1; + wacom->reset_tsc = tsc; + wacom->settings_bits.remote_mode = 0; + wacom->remote_req = 0; + wacom->settings_bits.out_of_range_data = 0; + + wacom_process_settings_dword(wacom, 0xE203C000); + mouse_mode = 1; } static void @@ -100,7 +229,23 @@ wacom_callback(struct serial_s *serial, void *priv) { mouse_wacom_t *wacom = (mouse_wacom_t *) priv; - wacom->transmit_period = wacom_transmit_period(wacom, 9600, -1); + switch(wacom->settings_bits.baud_rate) { + case 0: + wacom->transmit_period = wacom_transmit_period(wacom, 2400, -1); + break; + + case 1: + wacom->transmit_period = wacom_transmit_period(wacom, 4800, -1); + break; + + case 2: + wacom->transmit_period = wacom_transmit_period(wacom, 9600, -1); + break; + + case 3: + wacom->transmit_period = wacom_transmit_period(wacom, 19200, -1); + break; + } timer_stop(&wacom->report_timer); timer_on_auto(&wacom->report_timer, wacom->transmit_period); } @@ -130,7 +275,7 @@ wacom_write(struct serial_s *serial, void *priv, uint8_t data) if (data == '@') { wacom->remote_req = 1; - wacom->remote_mode = 1; + wacom->settings_bits.remote_mode = 1; return; } if (data == 0x13) { @@ -139,7 +284,7 @@ wacom_write(struct serial_s *serial, void *priv, uint8_t data) } if (data == 0x11) { wacom->transmission_stopped = 0; - wacom->remote_mode = wacom->remote_req = 0; + wacom->settings_bits.remote_mode = wacom->remote_req = 0; return; } wacom->data_rec[wacom->data_rec_pos++] = data; @@ -152,11 +297,10 @@ wacom_write(struct serial_s *serial, void *priv, uint8_t data) else pclog("Wacom: written %s\n", wacom->data_rec); if (!memcmp(wacom->data_rec, "AS", 2)) { - wacom->format = (wacom->data_rec[2] == '1'); - wacom->transmission_ongoing = 0; + wacom->settings_bits.output_format = !(wacom->data_rec[2] == '1'); + wacom->transmission_ongoing = 0; } else if (!memcmp(wacom->data_rec, "SR", 2)) { wacom->mode = WACOM_MODE_STREAM; - wacom->suppressed_increment = 0; } else if (!memcmp(wacom->data_rec, "IN", 2)) { sscanf((const char *) wacom->data_rec, "IN%d", &wacom->increment); } else if (!memcmp(wacom->data_rec, "RE", 2) || wacom->data_rec[0] == '$' || wacom->data_rec[0] == '#') { @@ -173,17 +317,23 @@ wacom_write(struct serial_s *serial, void *priv, uint8_t data) sscanf((const char *) wacom->data_rec, "PH%d", &wacom->pressure_mode); } else if (!memcmp(wacom->data_rec, "IC", 2)) { sscanf((const char *) wacom->data_rec, "IC%d", &wacom->measurement); + } else if (!memcmp(wacom->data_rec, "SW", 2)) { + wacom->mode = WACOM_MODE_SWITCH; } else if (!memcmp(wacom->data_rec, "AL", 2)) { - sscanf((const char *) wacom->data_rec, "AL%d", &wacom->always_report); + uint8_t out_of_range_data = wacom->settings_bits.out_of_range_data; + sscanf((const char *) wacom->data_rec, "AL%d", &out_of_range_data); + wacom->settings_bits.out_of_range_data = !!out_of_range_data; } else if (!memcmp(wacom->data_rec, "RQ", 2)) { - sscanf((const char *) wacom->data_rec, "RQ%d", &wacom->remote_mode); - if (wacom->remote_mode) + uint8_t remote_mode = 0; + sscanf((const char *) wacom->data_rec, "RQ%d", &remote_mode); + wacom->settings_bits.remote_mode = !!remote_mode; + if (wacom->settings_bits.remote_mode) wacom->remote_req = 1; } else if (!memcmp(wacom->data_rec, "SP", 2)) { wacom->transmission_stopped = 1; } else if (!memcmp(wacom->data_rec, "ST", 2)) { wacom->transmission_stopped = 0; - wacom->remote_mode = wacom->remote_req = 0; + wacom->settings_bits.remote_mode = wacom->remote_req = 0; } } } @@ -243,17 +393,17 @@ wacom_transmit_prepare(mouse_wacom_t *wacom, int x, int y) wacom->data_pos = 0; memset(wacom->data, 0, sizeof(wacom->data)); if (wacom->transmit_id) { - wacom->transmission_format = 0; + wacom->transmission_format = 1; snprintf((char *) wacom->data, sizeof(wacom->data), "~#SD51C V3.2.1.01\r"); return; } - wacom->transmission_format = wacom->format; + wacom->transmission_format = wacom->settings_bits.output_format; wacom->last_abs_x = wacom->abs_x; wacom->last_abs_y = wacom->abs_y; wacom->remote_req = 0; wacom->oldb = wacom->b; - if (wacom->format == 1) { + if (wacom->settings_bits.output_format == 0) { wacom->data[0] = 0xC0; wacom->data[6] = wacom->pressure_mode ? ((wacom->b & 0x1) ? (uint8_t) 31 : (uint8_t) -31) : wacom_get_switch(wacom->b); @@ -310,13 +460,13 @@ wacom_report_timer(void *priv) goto transmit_prepare; if (wacom->transmission_ongoing) goto transmit; - else if (wacom->remote_mode && !wacom->remote_req) + else if (wacom->settings_bits.remote_mode && !wacom->remote_req) return; else { - if (wacom->remote_mode && wacom->remote_req) { + if (wacom->settings_bits.remote_mode && wacom->remote_req) { goto transmit_prepare; } - if (wacom->transmission_stopped || (!mouse_tablet_in_proximity && !wacom->always_report)) + if (wacom->transmission_stopped || (!mouse_tablet_in_proximity && !wacom->settings_bits.out_of_range_data)) return; if (milisecond_diff >= (wacom->interval * 5)) { @@ -359,8 +509,8 @@ transmit_prepare: transmit: serial_write_fifo(wacom->serial, wacom->data[wacom->data_pos++]); - if ((wacom->transmission_format == 0 && wacom->data[wacom->data_pos] == 0) - || (wacom->transmission_format == 1 && wacom->data_pos == 7)) { + if ((wacom->transmission_format == 1 && wacom->data[wacom->data_pos] == 0) + || (wacom->transmission_format == 0 && wacom->data_pos == 7)) { wacom->transmission_ongoing = 0; wacom->transmit_id = 0; wacom->data_pos = 0; @@ -377,6 +527,7 @@ wacom_init(const device_t *info) dev = (mouse_wacom_t *) calloc(1, sizeof(mouse_wacom_t)); dev->name = info->name; dev->but = 3; + dev->bits = 10; dev->port = device_get_config_int("port"); From 90826277aa38dca99b39be6ac28ea891e05a2d43 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 3 Mar 2023 22:37:59 +0600 Subject: [PATCH 2/3] mouse_wacom_tablet: Make `data` a FIFO Windows 3.x Wacom handwriting mode now behaves correctly --- src/device/mouse_wacom_tablet.c | 136 +++++++++++++++++++++----------- 1 file changed, 88 insertions(+), 48 deletions(-) diff --git a/src/device/mouse_wacom_tablet.c b/src/device/mouse_wacom_tablet.c index 59b685ca5..a89c30d26 100644 --- a/src/device/mouse_wacom_tablet.c +++ b/src/device/mouse_wacom_tablet.c @@ -9,6 +9,7 @@ #include <86box/mouse.h> #include <86box/serial.h> #include <86box/plat.h> +#include <86box/fifo8.h> #define FLAG_3BTN 0x20 /* enable 3-button mode */ @@ -33,21 +34,29 @@ enum wacom_cmd_set { WACOM_CMDSET_IV = 3 }; +enum wacom_tablet_type { + WACOM_TYPE_IISONLY = 0, + WACOM_TYPE_IV, +}; + enum { REPORT_PHASE_PREPARE, REPORT_PHASE_TRANSMIT }; typedef struct wacom_tablet_id { - char id[512]; + char id[64]; + int type; } wacom_tablet_id; static const wacom_tablet_id sd510_id = { - .id = "~#SD51C V3.2.1.01\r" + .id = "~#SD51C V3.2.1.01\r", + .type = WACOM_TYPE_IISONLY }; static const wacom_tablet_id artpad_id = { - .id = "~#KT-0405-R00 V1.1-0\r" + .id = "~#KT-0405-R00 V1.1-0\r", + .type = WACOM_TYPE_IV }; typedef struct { @@ -56,13 +65,14 @@ typedef struct { port; uint8_t flags, but, /* device flags */ status, bits, - data_len, data[64], data_rec[0x200]; int abs_x, abs_y, rel_x, rel_y, oldb, b; - int data_pos, data_rec_pos, mode, transmission_ongoing, transmission_format, interval; + Fifo8 data; + + int data_rec_pos, mode, interval; int increment, suppressed_increment; int transmission_stopped; int reset; @@ -70,6 +80,9 @@ typedef struct { int pressure_mode; int suppressed, measurement; int remote_req; + + uint32_t x_res, y_res; + const wacom_tablet_id* tablet_type; int last_abs_x, last_abs_y; /* Suppressed/Increment Mode. */ union { @@ -150,7 +163,7 @@ wacom_process_settings_dword(mouse_wacom_t *wacom, uint32_t dword) wacom->mode = wacom->settings_bits.transfer_mode; - wacom->bits = 7 + wacom->settings_bits.data_bits_conf; + wacom->bits = 1 + 7 + wacom->settings_bits.data_bits_conf; wacom->bits += 1 + wacom->settings_bits.stop_bits_conf; if (wacom->settings_bits.parity == 2 && !(wacom->bits % 2)) { wacom->bits++; @@ -184,8 +197,6 @@ wacom_reset(mouse_wacom_t *wacom) { wacom->transmit_period = wacom_transmit_period(wacom, 9600, -1); wacom->mode = WACOM_MODE_POINT; - wacom->data_pos = 0; - wacom->transmission_ongoing = 0; wacom->transmission_stopped = 0; wacom->interval = 0; wacom->transmit_id = 0; @@ -206,8 +217,6 @@ wacom_reset_artpad(mouse_wacom_t *wacom) { wacom->transmit_period = wacom_transmit_period(wacom, 9600, -1); wacom->mode = WACOM_MODE_SUPPRESSED; - wacom->data_pos = 0; - wacom->transmission_ongoing = 0; wacom->transmission_stopped = 0; wacom->interval = 0; wacom->transmit_id = 0; @@ -264,8 +273,15 @@ wacom_write(struct serial_s *serial, void *priv, uint8_t data) switch (data) { case '#': { - if (!wacom->transmission_ongoing) - wacom->transmit_id++; + wacom->transmit_id = 1; + break; + } + case 'C': + case '*': + case 'R': + { + wacom->data_rec[wacom->data_rec_pos++] = '~'; + wacom->data_rec[wacom->data_rec_pos++] = data; break; } } @@ -296,9 +312,8 @@ wacom_write(struct serial_s *serial, void *priv, uint8_t data) pclog("Wacom: written %s", wacom->data_rec); else pclog("Wacom: written %s\n", wacom->data_rec); - if (!memcmp(wacom->data_rec, "AS", 2)) { + if (!memcmp(wacom->data_rec, "AS", 2) && wacom->settings_bits.cmd_set == WACOM_CMDSET_IIS) { wacom->settings_bits.output_format = !(wacom->data_rec[2] == '1'); - wacom->transmission_ongoing = 0; } else if (!memcmp(wacom->data_rec, "SR", 2)) { wacom->mode = WACOM_MODE_STREAM; } else if (!memcmp(wacom->data_rec, "IN", 2)) { @@ -307,13 +322,14 @@ wacom_write(struct serial_s *serial, void *priv, uint8_t data) wacom_reset(wacom); } else if (!memcmp(wacom->data_rec, "IT", 2)) { sscanf((const char *) wacom->data_rec, "IT%d", &wacom->interval); - } else if (!memcmp(wacom->data_rec, "DE", 2)) { + } else if (!memcmp(wacom->data_rec, "DE", 2) && wacom->settings_bits.cmd_set == WACOM_CMDSET_IIS) { sscanf((const char *) wacom->data_rec, "DE%d", &mouse_mode); mouse_mode = !mouse_mode; plat_mouse_capture(0); } else if (!memcmp(wacom->data_rec, "SU", 2)) { sscanf((const char *) wacom->data_rec, "SU%d", &wacom->suppressed_increment); - } else if (!memcmp(wacom->data_rec, "PH", 2)) { + pclog("Suppressed increment: %d\n", wacom->suppressed_increment); + } else if (!memcmp(wacom->data_rec, "PH", 2) && wacom->settings_bits.cmd_set == WACOM_CMDSET_IIS) { sscanf((const char *) wacom->data_rec, "PH%d", &wacom->pressure_mode); } else if (!memcmp(wacom->data_rec, "IC", 2)) { sscanf((const char *) wacom->data_rec, "IC%d", &wacom->measurement); @@ -321,7 +337,6 @@ wacom_write(struct serial_s *serial, void *priv, uint8_t data) wacom->mode = WACOM_MODE_SWITCH; } else if (!memcmp(wacom->data_rec, "AL", 2)) { uint8_t out_of_range_data = wacom->settings_bits.out_of_range_data; - sscanf((const char *) wacom->data_rec, "AL%d", &out_of_range_data); wacom->settings_bits.out_of_range_data = !!out_of_range_data; } else if (!memcmp(wacom->data_rec, "RQ", 2)) { uint8_t remote_mode = 0; @@ -334,6 +349,25 @@ wacom_write(struct serial_s *serial, void *priv, uint8_t data) } else if (!memcmp(wacom->data_rec, "ST", 2)) { wacom->transmission_stopped = 0; wacom->settings_bits.remote_mode = wacom->remote_req = 0; + } else if (wacom->tablet_type->type == WACOM_TYPE_IV && wacom->data_rec[0] == '~') { + if (!memcmp(wacom->data_rec, "~*", 2)) { + uint32_t settings_dword = wacom->settings; + if (strstr(wacom->data_rec, ",")) { + uint32_t x_res = wacom->x_res, y_res = wacom->y_res; + uint32_t increment = wacom->increment; + uint32_t interval = wacom->interval; + + sscanf("~*%X,%d,%d,%d,%d", wacom->data_rec, &settings_dword, &increment, &interval, &x_res, &y_res); + + wacom->interval = interval; + wacom->increment = increment; + wacom->x_res = x_res; + wacom->y_res = y_res; + } else { + sscanf("~*%X", wacom->data_rec, &settings_dword); + } + wacom_process_settings_dword(wacom, settings_dword); + } } } } @@ -389,54 +423,56 @@ wacom_get_switch(int b) static void wacom_transmit_prepare(mouse_wacom_t *wacom, int x, int y) { - wacom->transmission_ongoing = 1; - wacom->data_pos = 0; - memset(wacom->data, 0, sizeof(wacom->data)); if (wacom->transmit_id) { - wacom->transmission_format = 1; - snprintf((char *) wacom->data, sizeof(wacom->data), "~#SD51C V3.2.1.01\r"); + uint8_t data[128] = { 0 }; + snprintf((char *) data, sizeof(data), "~#SD51C V3.2.1.01\r"); + fifo8_push_all(&wacom->data, data, strlen(data)); + wacom->transmit_id = 0; return; } - wacom->transmission_format = wacom->settings_bits.output_format; wacom->last_abs_x = wacom->abs_x; wacom->last_abs_y = wacom->abs_y; wacom->remote_req = 0; wacom->oldb = wacom->b; if (wacom->settings_bits.output_format == 0) { - wacom->data[0] = 0xC0; - wacom->data[6] = wacom->pressure_mode ? ((wacom->b & 0x1) ? (uint8_t) 31 : (uint8_t) -31) : wacom_get_switch(wacom->b); + uint8_t data[7]; + data[0] = 0xC0; + data[6] = wacom->pressure_mode ? ((wacom->b & 0x1) ? (uint8_t) 31 : (uint8_t) -31) : wacom_get_switch(wacom->b); - wacom->data[5] = (y & 0x7F); - wacom->data[4] = ((y & 0x3F80) >> 7) & 0x7F; - wacom->data[3] = (((y & 0xC000) >> 14) & 3); + data[5] = (y & 0x7F); + data[4] = ((y & 0x3F80) >> 7) & 0x7F; + data[3] = (((y & 0xC000) >> 14) & 3); - wacom->data[2] = (x & 0x7F); - wacom->data[1] = ((x & 0x3F80) >> 7) & 0x7F; - wacom->data[0] |= (((x & 0xC000) >> 14) & 3); + data[2] = (x & 0x7F); + data[1] = ((x & 0x3F80) >> 7) & 0x7F; + data[0] |= (((x & 0xC000) >> 14) & 3); if (mouse_mode == 0) { - wacom->data[0] |= (!!(x < 0)) << 2; - wacom->data[3] |= (!!(y < 0)) << 2; + data[0] |= (!!(x < 0)) << 2; + data[3] |= (!!(y < 0)) << 2; } if (wacom->pressure_mode) { - wacom->data[0] |= 0x10; - wacom->data[6] &= 0x7F; + data[0] |= 0x10; + data[6] &= 0x7F; } if (tablet_tool_type == 1) { - wacom->data[0] |= 0x20; + data[0] |= 0x20; } if (!mouse_tablet_in_proximity) { - wacom->data[0] &= ~0x40; + data[0] &= ~0x40; } + fifo8_push_all(&wacom->data, data, 7); } else { - wacom->data[0] = 0; - snprintf((char *) wacom->data, sizeof(wacom->data), "*,%05d,%05d,%d\r\n", + uint8_t data[128]; + data[0] = 0; + snprintf((char *) data, sizeof(data), "*,%05d,%05d,%d\r\n", wacom->abs_x, wacom->abs_y, wacom->pressure_mode ? ((wacom->b & 0x1) ? (uint8_t) -31 : (uint8_t) 15) : ((wacom->b & 0x1) ? 21 : 00)); + fifo8_push_all(&wacom->data, data, strlen(data)); } } @@ -456,9 +492,9 @@ wacom_report_timer(void *priv) timer_on_auto(&wacom->report_timer, wacom->transmit_period); if ((((double) (tsc - wacom->reset_tsc)) / cpuclock * 1000.0) <= 10) return; - if (wacom->transmit_id && !wacom->transmission_ongoing) + if (wacom->transmit_id) goto transmit_prepare; - if (wacom->transmission_ongoing) + if (fifo8_num_used(&wacom->data)) goto transmit; else if (wacom->settings_bits.remote_mode && !wacom->remote_req) return; @@ -510,12 +546,8 @@ transmit_prepare: wacom_transmit_prepare(wacom, x, y); transmit: - serial_write_fifo(wacom->serial, wacom->data[wacom->data_pos++]); - if ((wacom->transmission_format == 1 && wacom->data[wacom->data_pos] == 0) - || (wacom->transmission_format == 0 && wacom->data_pos == 7)) { - wacom->transmission_ongoing = 0; - wacom->transmit_id = 0; - wacom->data_pos = 0; + serial_write_fifo(wacom->serial, fifo8_pop(&wacom->data)); + if (fifo8_num_used(&wacom->data) == 0) { wacom->old_tsc = tsc; } return; @@ -530,6 +562,12 @@ wacom_init(const device_t *info) dev->name = info->name; dev->but = 3; dev->bits = 10; + if (info->local == 0) { + dev->tablet_type = &sd510_id; + } else + dev->tablet_type = (wacom_tablet_id*)info->local; + + fifo8_create(&dev->data, 512); dev->port = device_get_config_int("port"); @@ -555,6 +593,8 @@ wacom_close(void *priv) { mouse_wacom_t *dev = (mouse_wacom_t *) priv; + fifo8_destroy(&dev->data); + /* Detach serial port from the mouse. */ if (dev && dev->serial && dev->serial->sd) memset(dev->serial->sd, 0, sizeof(serial_device_t)); @@ -588,7 +628,7 @@ const device_t mouse_wacom_device = { .name = "Wacom SD-510C", .internal_name = "wacom_serial", .flags = DEVICE_COM, - .local = MOUSE_TYPE_WACOM, + .local = 0, .init = wacom_init, .close = wacom_close, .reset = NULL, From ff0a39bbaaef95b895e7c3e0ae0bde892a7b8a0f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 4 Mar 2023 11:35:10 +0600 Subject: [PATCH 3/3] Add and enable Wacom ArtPad emulation --- src/device/mouse.c | 23 +++---- src/device/mouse_wacom_tablet.c | 113 +++++++++++++++++++++++++------- src/include/86box/mouse.h | 2 + 3 files changed, 105 insertions(+), 33 deletions(-) diff --git a/src/device/mouse.c b/src/device/mouse.c index 98ce0eaf4..7eb6a08a9 100644 --- a/src/device/mouse.c +++ b/src/device/mouse.c @@ -75,19 +75,20 @@ static const device_t mouse_internal_device = { static mouse_t mouse_devices[] = { // clang-format off - { &mouse_none_device }, - { &mouse_internal_device }, - { &mouse_logibus_device }, - { &mouse_msinport_device }, + { &mouse_none_device }, + { &mouse_internal_device }, + { &mouse_logibus_device }, + { &mouse_msinport_device }, #if 0 - { &mouse_genibus_device }, + { &mouse_genibus_device }, #endif - { &mouse_mssystems_device }, - { &mouse_msserial_device }, - { &mouse_ltserial_device }, - { &mouse_ps2_device }, - { &mouse_wacom_device }, - { NULL } + { &mouse_mssystems_device }, + { &mouse_msserial_device }, + { &mouse_ltserial_device }, + { &mouse_ps2_device }, + { &mouse_wacom_device }, + { &mouse_wacom_artpad_device }, + { NULL } // clang-format on }; diff --git a/src/device/mouse_wacom_tablet.c b/src/device/mouse_wacom_tablet.c index a89c30d26..673104007 100644 --- a/src/device/mouse_wacom_tablet.c +++ b/src/device/mouse_wacom_tablet.c @@ -59,6 +59,13 @@ static const wacom_tablet_id artpad_id = { .type = WACOM_TYPE_IV }; +static const uint32_t wacom_resolution_values[4] = { + 500, + 508, + 1000, + 1270 +}; + typedef struct { const char *name; /* name of this device */ int8_t type, /* type of this device */ @@ -190,6 +197,7 @@ wacom_process_settings_dword(mouse_wacom_t *wacom, uint32_t dword) } mouse_mode = !wacom->settings_bits.coord_sys; + wacom->x_res = wacom->y_res = wacom_resolution_values[wacom->settings_bits.resolution]; } static void @@ -294,6 +302,14 @@ wacom_write(struct serial_s *serial, void *priv, uint8_t data) wacom->settings_bits.remote_mode = 1; return; } + if (data == '#' && wacom->tablet_type->type == WACOM_TYPE_IV) { + wacom_reset_artpad(wacom); + return; + } + if (data == '$') { + wacom_reset(wacom); + return; + } if (data == 0x13) { wacom->transmission_stopped = 1; return; @@ -318,8 +334,9 @@ wacom_write(struct serial_s *serial, void *priv, uint8_t data) wacom->mode = WACOM_MODE_STREAM; } else if (!memcmp(wacom->data_rec, "IN", 2)) { sscanf((const char *) wacom->data_rec, "IN%d", &wacom->increment); - } else if (!memcmp(wacom->data_rec, "RE", 2) || wacom->data_rec[0] == '$' || wacom->data_rec[0] == '#') { - wacom_reset(wacom); + } else if (!memcmp(wacom->data_rec, "RE", 2)) { + if (wacom->tablet_type->type == WACOM_TYPE_IV) wacom_reset_artpad(wacom); + else wacom_reset(wacom); } else if (!memcmp(wacom->data_rec, "IT", 2)) { sscanf((const char *) wacom->data_rec, "IT%d", &wacom->interval); } else if (!memcmp(wacom->data_rec, "DE", 2) && wacom->settings_bits.cmd_set == WACOM_CMDSET_IIS) { @@ -328,7 +345,7 @@ wacom_write(struct serial_s *serial, void *priv, uint8_t data) plat_mouse_capture(0); } else if (!memcmp(wacom->data_rec, "SU", 2)) { sscanf((const char *) wacom->data_rec, "SU%d", &wacom->suppressed_increment); - pclog("Suppressed increment: %d\n", wacom->suppressed_increment); + wacom->settings_bits.transfer_mode = wacom->mode = WACOM_MODE_SUPPRESSED; } else if (!memcmp(wacom->data_rec, "PH", 2) && wacom->settings_bits.cmd_set == WACOM_CMDSET_IIS) { sscanf((const char *) wacom->data_rec, "PH%d", &wacom->pressure_mode); } else if (!memcmp(wacom->data_rec, "IC", 2)) { @@ -348,7 +365,10 @@ wacom_write(struct serial_s *serial, void *priv, uint8_t data) wacom->transmission_stopped = 1; } else if (!memcmp(wacom->data_rec, "ST", 2)) { wacom->transmission_stopped = 0; - wacom->settings_bits.remote_mode = wacom->remote_req = 0; + wacom->settings_bits.remote_mode = wacom->remote_req = 0; + } else if (!memcmp(wacom->data_rec, "NR", 2)) { + sscanf((const char *) wacom->data_rec, "NR%d", &wacom->x_res); + wacom->y_res = wacom->x_res; } else if (wacom->tablet_type->type == WACOM_TYPE_IV && wacom->data_rec[0] == '~') { if (!memcmp(wacom->data_rec, "~*", 2)) { uint32_t settings_dword = wacom->settings; @@ -357,7 +377,7 @@ wacom_write(struct serial_s *serial, void *priv, uint8_t data) uint32_t increment = wacom->increment; uint32_t interval = wacom->interval; - sscanf("~*%X,%d,%d,%d,%d", wacom->data_rec, &settings_dword, &increment, &interval, &x_res, &y_res); + sscanf("~*%08X,%d,%d,%d,%d", wacom->data_rec, &settings_dword, &increment, &interval, &x_res, &y_res); wacom->interval = interval; wacom->increment = increment; @@ -367,6 +387,12 @@ wacom_write(struct serial_s *serial, void *priv, uint8_t data) sscanf("~*%X", wacom->data_rec, &settings_dword); } wacom_process_settings_dword(wacom, settings_dword); + } else if (!memcmp(wacom->data_rec, "~C", 2)) { + fifo8_push_all(&wacom->data, "~C5039,3779\r", sizeof("~C5039,3779\r") - 1); + } else if (!memcmp(wacom->data_rec, "~R", 2)) { + uint8_t data[256] = { 0 }; + snprintf(data, sizeof(data), "~*%08X,%d,%d,%d,%d\r", wacom->settings, wacom->increment, wacom->x_res, wacom->y_res); + fifo8_push_all(&wacom->data, data, strlen(data)); } } } @@ -376,18 +402,24 @@ static int wacom_poll(int x, int y, int z, int b, double abs_x, double abs_y, void *priv) { mouse_wacom_t *wacom = (mouse_wacom_t *) priv; - wacom->abs_x = abs_x * (wacom->measurement ? 4566. : 5800.); - wacom->abs_y = abs_y * (wacom->measurement ? 2972. : 3774.); - if (wacom->abs_x > (wacom->measurement ? 4566 : 5800)) - wacom->abs_x = (wacom->measurement ? 4566 : 5800); - if (wacom->abs_y > (wacom->measurement ? 2972 : 3774)) - wacom->abs_x = (wacom->measurement ? 2972 : 3774); - if (wacom->abs_x < 0) - wacom->abs_x = 0; - if (wacom->abs_y < 0) - wacom->abs_y = 0; - wacom->rel_x = x; - wacom->rel_y = y; + + if (wacom->settings_bits.cmd_set == WACOM_CMDSET_IV) { + wacom->abs_x = abs_x * 5039. * (wacom->x_res / 1000.); + wacom->abs_y = abs_y * 3779. * (wacom->y_res / 1000.); + } else { + wacom->abs_x = abs_x * (wacom->measurement ? 4566. : 5800.); + wacom->abs_y = abs_y * (wacom->measurement ? 2972. : 3774.); + if (wacom->abs_x > (wacom->measurement ? 4566 : 5800)) + wacom->abs_x = (wacom->measurement ? 4566 : 5800); + if (wacom->abs_y > (wacom->measurement ? 2972 : 3774)) + wacom->abs_x = (wacom->measurement ? 2972 : 3774); + if (wacom->abs_x < 0) + wacom->abs_x = 0; + if (wacom->abs_y < 0) + wacom->abs_y = 0; + wacom->rel_x = x; + wacom->rel_y = y; + } if (wacom->b != b) wacom->oldb = wacom->b; wacom->b = b; @@ -425,7 +457,7 @@ wacom_transmit_prepare(mouse_wacom_t *wacom, int x, int y) { if (wacom->transmit_id) { uint8_t data[128] = { 0 }; - snprintf((char *) data, sizeof(data), "~#SD51C V3.2.1.01\r"); + snprintf((char *) data, sizeof(data), "%s", wacom->tablet_type->id); fifo8_push_all(&wacom->data, data, strlen(data)); wacom->transmit_id = 0; return; @@ -438,7 +470,14 @@ wacom_transmit_prepare(mouse_wacom_t *wacom, int x, int y) if (wacom->settings_bits.output_format == 0) { uint8_t data[7]; data[0] = 0xC0; - data[6] = wacom->pressure_mode ? ((wacom->b & 0x1) ? (uint8_t) 31 : (uint8_t) -31) : wacom_get_switch(wacom->b); + if (wacom->settings_bits.cmd_set == WACOM_CMDSET_IV) { + if (tablet_tool_type == 0) + data[6] = ((wacom->b & 0x1) ? (uint8_t) 31 : (uint8_t) -1); + else + data[6] = ((wacom->b & 0x1) ? (uint8_t) 63 : (uint8_t) -63); + } + else + data[6] = (wacom->pressure_mode || wacom->settings_bits.cmd_set == WACOM_CMDSET_IV) ? ((wacom->b & 0x1) ? (uint8_t) 31 : (uint8_t) -31) : wacom_get_switch(wacom->b); data[5] = (y & 0x7F); data[4] = ((y & 0x3F80) >> 7) & 0x7F; @@ -448,12 +487,21 @@ wacom_transmit_prepare(mouse_wacom_t *wacom, int x, int y) data[1] = ((x & 0x3F80) >> 7) & 0x7F; data[0] |= (((x & 0xC000) >> 14) & 3); - if (mouse_mode == 0) { + if (mouse_mode == 0 && wacom->settings_bits.cmd_set == WACOM_CMDSET_IIS) { data[0] |= (!!(x < 0)) << 2; data[3] |= (!!(y < 0)) << 2; } - if (wacom->pressure_mode) { + if (wacom->settings_bits.cmd_set == WACOM_CMDSET_IV) { + data[6] &= 0x7F; + data[3] &= 0x3; + if (wacom_get_switch(wacom->b) != 0x21) { + data[3] |= (wacom_get_switch(wacom->b) & 0xF) << 3; + data[0] |= 0x8; + } + } + + if (wacom->pressure_mode && wacom->settings_bits.cmd_set == WACOM_CMDSET_IIS) { data[0] |= 0x10; data[6] &= 0x7F; } @@ -533,6 +581,9 @@ wacom_report_timer(void *priv) } } + if (increment && !mouse_tablet_in_proximity) + return; + if (increment && !(x_diff > increment || y_diff > increment)) { if (wacom->suppressed_increment && (wacom->b == wacom->oldb)) return; @@ -575,7 +626,11 @@ wacom_init(const device_t *info) timer_add(&dev->report_timer, wacom_report_timer, dev, 0); mouse_set_buttons(dev->but); - wacom_reset(dev); + if (dev->tablet_type->type == WACOM_TYPE_IV) { + wacom_reset_artpad(dev); + wacom_process_settings_dword(dev, 0xE2018000); + } + else wacom_reset(dev); return dev; } @@ -637,3 +692,17 @@ const device_t mouse_wacom_device = { .force_redraw = NULL, .config = wacom_config }; + +const device_t mouse_wacom_artpad_device = { + .name = "Wacom ArtPad", + .internal_name = "wacom_serial_artpad", + .flags = DEVICE_COM, + .local = (uintptr_t)&artpad_id, + .init = wacom_init, + .close = wacom_close, + .reset = NULL, + { .poll = wacom_poll }, + .speed_changed = wacom_speed_changed, + .force_redraw = NULL, + .config = wacom_config +}; diff --git a/src/include/86box/mouse.h b/src/include/86box/mouse.h index e6ad93e80..317e267a0 100644 --- a/src/include/86box/mouse.h +++ b/src/include/86box/mouse.h @@ -35,6 +35,7 @@ #define MOUSE_TYPE_LT3BUTTON 10 /* Logitech 3-button Serial Mouse */ #define MOUSE_TYPE_PS2 11 /* PS/2 series Bus Mouse */ #define MOUSE_TYPE_WACOM 12 /* WACOM tablet */ +#define MOUSE_TYPE_WACOMARTP 13 /* WACOM tablet (ArtPad) */ #define MOUSE_TYPE_ONBOARD 0x80 /* Mouse is an on-board version of one of the above. */ @@ -65,6 +66,7 @@ extern const device_t mouse_msserial_device; extern const device_t mouse_ltserial_device; extern const device_t mouse_ps2_device; extern const device_t mouse_wacom_device; +extern const device_t mouse_wacom_artpad_device; #endif extern void mouse_init(void);