12089Ssos// SPDX-License-Identifier: GPL-2.0-or-later 216565Ssos/* 32089Ssos * Wacom protocol 4 serial tablet driver 42089Ssos * 52089Ssos * Copyright 2014 Hans de Goede <hdegoede@redhat.com> 62089Ssos * Copyright 2011-2012 Julian Squires <julian@cipht.net> 72089Ssos * 82089Ssos * Many thanks to Bill Seremetis, without whom PenPartner support 95994Ssos * would not have been possible. Thanks to Patrick Mahoney. 105994Ssos * 112089Ssos * This driver was developed with reference to much code written by others, 122089Ssos * particularly: 132089Ssos * - elo, gunze drivers by Vojtech Pavlik <vojtech@ucw.cz>; 142089Ssos * - wacom_w8001 driver by Jaya Kumar <jayakumar.lkml@gmail.com>; 152089Ssos * - the USB wacom input driver, credited to many people 162089Ssos * (see drivers/input/tablet/wacom.h); 172089Ssos * - new and old versions of linuxwacom / xf86-input-wacom credited to 182089Ssos * Frederic Lepied, France. <Lepied@XFree86.org> and 192089Ssos * Ping Cheng, Wacom. <pingc@wacom.com>; 202089Ssos * - and xf86wacom.c (a presumably ancient version of the linuxwacom code), 212089Ssos * by Frederic Lepied and Raph Levien <raph@gtk.org>. 222089Ssos * 232089Ssos * To do: 242089Ssos * - support pad buttons; (requires access to a model with pad buttons) 252089Ssos * - support (protocol 4-style) tilt (requires access to a > 1.4 rom model) 262089Ssos */ 272089Ssos 282089Ssos/* 2930764Scharnier * Wacom serial protocol 4 documentation taken from linuxwacom-0.9.9 code, 3030764Scharnier * protocol 4 uses 7 or 9 byte of data in the following format: 3150479Speter * 3230764Scharnier * Byte 1 3330764Scharnier * bit 7 Sync bit always 1 342089Ssos * bit 6 Pointing device detected 3530764Scharnier * bit 5 Cursor = 0 / Stylus = 1 3655849Syokota * bit 4 Reserved 372089Ssos * bit 3 1 if a button on the pointing device has been pressed 3823457Sbrian * bit 2 P0 (optional) 3930764Scharnier * bit 1 X15 4023702Speter * bit 0 X14 412089Ssos * 422089Ssos * Byte 2 432089Ssos * bit 7 Always 0 4423457Sbrian * bits 6-0 = X13 - X7 452089Ssos * 462089Ssos * Byte 3 472089Ssos * bit 7 Always 0 482089Ssos * bits 6-0 = X6 - X0 492089Ssos * 502089Ssos * Byte 4 516628Ssos * bit 7 Always 0 522089Ssos * bit 6 B3 536047Ssos * bit 5 B2 542089Ssos * bit 4 B1 552089Ssos * bit 3 B0 562089Ssos * bit 2 P1 (optional) 572089Ssos * bit 1 Y15 5830764Scharnier * bit 0 Y14 596628Ssos * 606628Ssos * Byte 5 6155849Syokota * bit 7 Always 0 6230764Scharnier * bits 6-0 = Y13 - Y7 6355849Syokota * 6455849Syokota * Byte 6 6555849Syokota * bit 7 Always 0 6630764Scharnier * bits 6-0 = Y6 - Y0 676628Ssos * 686628Ssos * Byte 7 692089Ssos * bit 7 Always 0 702089Ssos * bit 6 Sign of pressure data; or wheel-rel for cursor tool 712089Ssos * bit 5 P7; or REL1 for cursor tool 722089Ssos * bit 4 P6; or REL0 for cursor tool 732089Ssos * bit 3 P5 7430764Scharnier * bit 2 P4 752089Ssos * bit 1 P3 762089Ssos * bit 0 P2 772089Ssos * 782089Ssos * byte 8 and 9 are optional and present only 792089Ssos * in tilt mode. 802089Ssos * 816628Ssos * Byte 8 826628Ssos * bit 7 Always 0 836628Ssos * bit 6 Sign of tilt X 842089Ssos * bit 5 Xt6 852089Ssos * bit 4 Xt5 8652262Sbillf * bit 3 Xt4 872089Ssos * bit 2 Xt3 882089Ssos * bit 1 Xt2 892089Ssos * bit 0 Xt1 902089Ssos * 9152262Sbillf * Byte 9 922089Ssos * bit 7 Always 0 932089Ssos * bit 6 Sign of tilt Y 942089Ssos * bit 5 Yt6 952089Ssos * bit 4 Yt5 962089Ssos * bit 3 Yt4 972089Ssos * bit 2 Yt3 982089Ssos * bit 1 Yt2 992089Ssos * bit 0 Yt1 1002089Ssos */ 1012089Ssos 1022089Ssos#include <linux/completion.h> 1032089Ssos#include <linux/init.h> 1042089Ssos#include <linux/input.h> 1052089Ssos#include <linux/interrupt.h> 1062089Ssos#include <linux/kernel.h> 10723457Sbrian#include <linux/module.h> 1082089Ssos#include <linux/serio.h> 1092089Ssos#include <linux/slab.h> 1102089Ssos#include <linux/string.h> 1112089Ssos 1122089SsosMODULE_AUTHOR("Julian Squires <julian@cipht.net>, Hans de Goede <hdegoede@redhat.com>"); 1132089SsosMODULE_DESCRIPTION("Wacom protocol 4 serial tablet driver"); 1142089SsosMODULE_LICENSE("GPL"); 1152089Ssos 11623457Sbrian#define REQUEST_MODEL_AND_ROM_VERSION "~#" 11723457Sbrian#define REQUEST_MAX_COORDINATES "~C\r" 1182089Ssos#define REQUEST_CONFIGURATION_STRING "~R\r" 1192089Ssos#define REQUEST_RESET_TO_PROTOCOL_IV "\r#" 1202089Ssos/* 12130764Scharnier * Note: sending "\r$\r" causes at least the Digitizer II to send 1222089Ssos * packets in ASCII instead of binary. "\r#" seems to undo that. 1232089Ssos */ 1242089Ssos 12523457Sbrian#define COMMAND_START_SENDING_PACKETS "ST\r" 1262089Ssos#define COMMAND_STOP_SENDING_PACKETS "SP\r" 1272089Ssos#define COMMAND_MULTI_MODE_INPUT "MU1\r" 12830764Scharnier#define COMMAND_ORIGIN_IN_UPPER_LEFT "OC1\r" 12923457Sbrian#define COMMAND_ENABLE_ALL_MACRO_BUTTONS "~M0\r" 1302089Ssos#define COMMAND_DISABLE_GROUP_1_MACRO_BUTTONS "~M1\r" 1312089Ssos#define COMMAND_TRANSMIT_AT_MAX_RATE "IT0\r" 1322089Ssos#define COMMAND_DISABLE_INCREMENTAL_MODE "IN0\r" 1332089Ssos#define COMMAND_ENABLE_CONTINUOUS_MODE "SR\r" 13430764Scharnier#define COMMAND_ENABLE_PRESSURE_MODE "PH1\r" 13523457Sbrian#define COMMAND_Z_FILTER "ZF1\r" 1362089Ssos 1372089Ssos/* Note that this is a protocol 4 packet without tilt information. */ 1382089Ssos#define PACKET_LENGTH 7 1392089Ssos#define DATA_SIZE 32 1402089Ssos 1416628Ssos/* flags */ 1422089Ssos#define F_COVERS_SCREEN 0x01 1432089Ssos#define F_HAS_STYLUS2 0x02 1442089Ssos#define F_HAS_SCROLLWHEEL 0x04 1452089Ssos 1462089Ssos/* device IDs */ 14730764Scharnier#define STYLUS_DEVICE_ID 0x02 1482089Ssos#define CURSOR_DEVICE_ID 0x06 1492089Ssos#define ERASER_DEVICE_ID 0x0A 1502089Ssos 1512089Ssosenum { STYLUS = 1, ERASER, CURSOR }; 1522089Ssos 1532089Ssosstatic const struct { 1542089Ssos int device_id; 1552089Ssos int input_id; 1562089Ssos} tools[] = { 15730764Scharnier { 0, 0 }, 1582089Ssos { STYLUS_DEVICE_ID, BTN_TOOL_PEN }, 1592089Ssos { ERASER_DEVICE_ID, BTN_TOOL_RUBBER }, 1602089Ssos { CURSOR_DEVICE_ID, BTN_TOOL_MOUSE }, 1612089Ssos}; 1622089Ssos 1632089Ssosstruct wacom { 1648857Srgrimes struct input_dev *dev; 1652089Ssos struct completion cmd_done; 1662089Ssos int result; 1672089Ssos u8 expect; 1682089Ssos u8 eraser_mask; 1692089Ssos unsigned int extra_z_bits; 1702089Ssos unsigned int flags; 1712089Ssos unsigned int res_x, res_y; 1728857Srgrimes unsigned int max_x, max_y; 1732089Ssos unsigned int tool; 1742089Ssos unsigned int idx; 17523457Sbrian u8 data[DATA_SIZE]; 17637636Sbde char phys[32]; 17737636Sbde}; 1782089Ssos 1792089Ssosenum { 1802089Ssos MODEL_CINTIQ = 0x504C, /* PL */ 1812089Ssos MODEL_CINTIQ2 = 0x4454, /* DT */ 1822089Ssos MODEL_DIGITIZER_II = 0x5544, /* UD */ 1832089Ssos MODEL_GRAPHIRE = 0x4554, /* ET */ 18423457Sbrian MODEL_PENPARTNER = 0x4354, /* CT */ 18523457Sbrian MODEL_ARTPAD_II = 0x4B54, /* KT */ 1862089Ssos}; 1872089Ssos 1882089Ssosstatic void wacom_handle_model_response(struct wacom *wacom) 18930764Scharnier{ 1902089Ssos int major_v, minor_v, r = 0; 1912089Ssos char *p; 1922089Ssos 1932089Ssos p = strrchr(wacom->data, 'V'); 1942089Ssos if (p) 1952089Ssos r = sscanf(p + 1, "%u.%u", &major_v, &minor_v); 1962089Ssos if (r != 2) 1972089Ssos major_v = minor_v = 0; 1982089Ssos 1992089Ssos switch (wacom->data[2] << 8 | wacom->data[3]) { 2002089Ssos case MODEL_CINTIQ: /* UNTESTED */ 2012089Ssos case MODEL_CINTIQ2: 2022089Ssos if ((wacom->data[2] << 8 | wacom->data[3]) == MODEL_CINTIQ) { 2032089Ssos wacom->dev->name = "Wacom Cintiq"; 2042089Ssos wacom->dev->id.version = MODEL_CINTIQ; 20530764Scharnier } else { 20623457Sbrian wacom->dev->name = "Wacom Cintiq II"; 2072089Ssos wacom->dev->id.version = MODEL_CINTIQ2; 2082089Ssos } 2092089Ssos wacom->res_x = 508; 2102089Ssos wacom->res_y = 508; 2112089Ssos 2122089Ssos switch (wacom->data[5] << 8 | wacom->data[6]) { 21330764Scharnier case 0x3731: /* PL-710 */ 21423457Sbrian wacom->res_x = 2540; 2152089Ssos wacom->res_y = 2540; 2162089Ssos fallthrough; 2172089Ssos case 0x3535: /* PL-550 */ 2182089Ssos case 0x3830: /* PL-800 */ 2192089Ssos wacom->extra_z_bits = 2; 22030764Scharnier } 22123457Sbrian 2222089Ssos wacom->flags = F_COVERS_SCREEN; 2232089Ssos break; 2242089Ssos 2252089Ssos case MODEL_PENPARTNER: 2262089Ssos wacom->dev->name = "Wacom Penpartner"; 2272089Ssos wacom->dev->id.version = MODEL_PENPARTNER; 2282089Ssos wacom->res_x = 1000; 2292089Ssos wacom->res_y = 1000; 2302089Ssos break; 2312089Ssos 2322089Ssos case MODEL_GRAPHIRE: 2332089Ssos wacom->dev->name = "Wacom Graphire"; 2342089Ssos wacom->dev->id.version = MODEL_GRAPHIRE; 23530764Scharnier wacom->res_x = 1016; 2362089Ssos wacom->res_y = 1016; 2372089Ssos wacom->max_x = 5103; 2382089Ssos wacom->max_y = 3711; 2392089Ssos wacom->extra_z_bits = 2; 24030764Scharnier wacom->eraser_mask = 0x08; 2412089Ssos wacom->flags = F_HAS_STYLUS2 | F_HAS_SCROLLWHEEL; 2422089Ssos break; 2432089Ssos 2445536Ssos case MODEL_ARTPAD_II: 2452089Ssos case MODEL_DIGITIZER_II: 2465536Ssos wacom->dev->name = "Wacom Digitizer II"; 2472089Ssos wacom->dev->id.version = MODEL_DIGITIZER_II; 2486230Ssos if (major_v == 1 && minor_v <= 2) 2496230Ssos wacom->extra_z_bits = 0; /* UNTESTED */ 2506230Ssos break; 2515536Ssos 2526230Ssos default: 2536230Ssos dev_err(&wacom->dev->dev, "Unsupported Wacom model %s\n", 2545536Ssos wacom->data); 25530764Scharnier wacom->result = -ENODEV; 2562089Ssos return; 2572089Ssos } 2585536Ssos 2592089Ssos dev_info(&wacom->dev->dev, "%s tablet, version %u.%u\n", 2602089Ssos wacom->dev->name, major_v, minor_v); 26123457Sbrian} 2622089Ssos 2632089Ssosstatic void wacom_handle_configuration_response(struct wacom *wacom) 26439592Syokota{ 26539592Syokota int r, skip; 26639592Syokota 26739592Syokota dev_dbg(&wacom->dev->dev, "Configuration string: %s\n", wacom->data); 26839592Syokota r = sscanf(wacom->data, "~R%x,%u,%u,%u,%u", &skip, &skip, &skip, 26939592Syokota &wacom->res_x, &wacom->res_y); 27039592Syokota if (r != 5) 27139592Syokota dev_warn(&wacom->dev->dev, "could not get resolution\n"); 27239592Syokota} 27339592Syokota 27439592Syokotastatic void wacom_handle_coordinates_response(struct wacom *wacom) 27539592Syokota{ 27639592Syokota int r; 27739592Syokota 27839592Syokota dev_dbg(&wacom->dev->dev, "Coordinates string: %s\n", wacom->data); 27939592Syokota r = sscanf(wacom->data, "~C%u,%u", &wacom->max_x, &wacom->max_y); 28039592Syokota if (r != 2) 28139592Syokota dev_warn(&wacom->dev->dev, "could not get max coordinates\n"); 28239592Syokota} 28348105Syokota 28448105Syokotastatic void wacom_handle_response(struct wacom *wacom) 28548105Syokota{ 28648105Syokota if (wacom->data[0] != '~' || wacom->data[1] != wacom->expect) { 28748105Syokota dev_err(&wacom->dev->dev, 28848105Syokota "Wacom got an unexpected response: %s\n", wacom->data); 28948105Syokota wacom->result = -EIO; 29039592Syokota } else { 29139592Syokota wacom->result = 0; 29239592Syokota 29339592Syokota switch (wacom->data[1]) { 29439592Syokota case '#': 29539592Syokota wacom_handle_model_response(wacom); 29639592Syokota break; 29739592Syokota case 'R': 29839592Syokota wacom_handle_configuration_response(wacom); 29939592Syokota break; 30042605Smjacob case 'C': 30148105Syokota wacom_handle_coordinates_response(wacom); 30248105Syokota break; 30339287Ssos } 30439592Syokota } 3052089Ssos 30648105Syokota complete(&wacom->cmd_done); 30748105Syokota} 3082089Ssos 30939592Syokotastatic void wacom_handle_packet(struct wacom *wacom) 31039592Syokota{ 31139592Syokota u8 in_proximity_p, stylus_p, button; 31239592Syokota unsigned int tool; 31339592Syokota int x, y, z; 31439592Syokota 31539592Syokota in_proximity_p = wacom->data[0] & 0x40; 3162089Ssos stylus_p = wacom->data[0] & 0x20; 3172089Ssos button = (wacom->data[3] & 0x78) >> 3; 31830764Scharnier x = (wacom->data[0] & 3) << 14 | wacom->data[1]<<7 | wacom->data[2]; 31939287Ssos y = (wacom->data[3] & 3) << 14 | wacom->data[4]<<7 | wacom->data[5]; 32039287Ssos 32139287Ssos if (in_proximity_p && stylus_p) { 32239287Ssos z = wacom->data[6] & 0x7f; 32348105Syokota if (wacom->extra_z_bits >= 1) 32448105Syokota z = z << 1 | (wacom->data[3] & 0x4) >> 2; 32548105Syokota if (wacom->extra_z_bits > 1) 32648105Syokota z = z << 1 | (wacom->data[0] & 0x4) >> 2; 32748105Syokota z = z ^ (0x40 << wacom->extra_z_bits); 32848105Syokota } else { 32948105Syokota z = -1; 33048105Syokota } 33139287Ssos 3322089Ssos if (stylus_p) 3332089Ssos tool = (button & wacom->eraser_mask) ? ERASER : STYLUS; 3342089Ssos else 3352089Ssos tool = CURSOR; 3368857Srgrimes 3372089Ssos if (tool != wacom->tool && wacom->tool != 0) { 3382089Ssos input_report_key(wacom->dev, tools[wacom->tool].input_id, 0); 3392089Ssos input_sync(wacom->dev); 3402089Ssos } 3412089Ssos wacom->tool = tool; 3422089Ssos 3432089Ssos input_report_key(wacom->dev, tools[tool].input_id, in_proximity_p); 3442089Ssos input_report_abs(wacom->dev, ABS_MISC, 3452089Ssos in_proximity_p ? tools[tool].device_id : 0); 3462089Ssos input_report_abs(wacom->dev, ABS_X, x); 3472089Ssos input_report_abs(wacom->dev, ABS_Y, y); 34823457Sbrian input_report_abs(wacom->dev, ABS_PRESSURE, z); 3492089Ssos if (stylus_p) { 3502089Ssos input_report_key(wacom->dev, BTN_TOUCH, button & 1); 3512089Ssos input_report_key(wacom->dev, BTN_STYLUS, button & 2); 3522089Ssos input_report_key(wacom->dev, BTN_STYLUS2, button & 4); 3532089Ssos } else { 3542089Ssos input_report_key(wacom->dev, BTN_LEFT, button & 1); 3552089Ssos input_report_key(wacom->dev, BTN_RIGHT, button & 2); 3568857Srgrimes input_report_key(wacom->dev, BTN_MIDDLE, button & 4); 3578857Srgrimes /* handle relative wheel for non-stylus device */ 3582089Ssos z = (wacom->data[6] & 0x30) >> 4; 3592089Ssos if (wacom->data[6] & 0x40) 3602089Ssos z = -z; 3612089Ssos input_report_rel(wacom->dev, REL_WHEEL, z); 3622089Ssos } 3632089Ssos input_sync(wacom->dev); 3642089Ssos} 36523457Sbrian 3662089Ssosstatic void wacom_clear_data_buf(struct wacom *wacom) 3672089Ssos{ 3682089Ssos memset(wacom->data, 0, DATA_SIZE); 3692089Ssos wacom->idx = 0; 3702089Ssos} 3712089Ssos 3728857Srgrimesstatic irqreturn_t wacom_interrupt(struct serio *serio, unsigned char data, 3738857Srgrimes unsigned int flags) 3742089Ssos{ 3752089Ssos struct wacom *wacom = serio_get_drvdata(serio); 3762089Ssos 3772089Ssos if (data & 0x80) 3782089Ssos wacom->idx = 0; 3792089Ssos 3802089Ssos /* 38123457Sbrian * We're either expecting a carriage return-terminated ASCII 38223457Sbrian * response string, or a seven-byte packet with the MSB set on 38323457Sbrian * the first byte. 38423457Sbrian * 38523457Sbrian * Note however that some tablets (the PenPartner, for 38623457Sbrian * example) don't send a carriage return at the end of a 38730764Scharnier * command. We handle these by waiting for timeout. 38823457Sbrian */ 38923457Sbrian if (data == '\r' && !(wacom->data[0] & 0x80)) { 39023457Sbrian wacom_handle_response(wacom); 39123457Sbrian wacom_clear_data_buf(wacom); 39251393Syokota return IRQ_HANDLED; 39330764Scharnier } 39442605Smjacob 39530764Scharnier /* Leave place for 0 termination */ 39623457Sbrian if (wacom->idx > (DATA_SIZE - 2)) { 39723457Sbrian dev_dbg(&wacom->dev->dev, 39823457Sbrian "throwing away %d bytes of garbage\n", wacom->idx); 3992089Ssos wacom_clear_data_buf(wacom); 4002089Ssos } 4012089Ssos wacom->data[wacom->idx++] = data; 4022089Ssos 4032089Ssos if (wacom->idx == PACKET_LENGTH && (wacom->data[0] & 0x80)) { 4042089Ssos wacom_handle_packet(wacom); 4052089Ssos wacom_clear_data_buf(wacom); 4062089Ssos } 4078857Srgrimes 4082089Ssos return IRQ_HANDLED; 4092089Ssos} 41016565Ssos 41155849Syokotastatic void wacom_disconnect(struct serio *serio) 41255849Syokota{ 41355849Syokota struct wacom *wacom = serio_get_drvdata(serio); 41455849Syokota 41555849Syokota serio_close(serio); 41655849Syokota serio_set_drvdata(serio, NULL); 41755849Syokota input_unregister_device(wacom->dev); 41855849Syokota kfree(wacom); 41955849Syokota} 42055849Syokota 42155849Syokotastatic int wacom_send(struct serio *serio, const u8 *command) 42255849Syokota{ 42355849Syokota int err = 0; 42455849Syokota 42555849Syokota for (; !err && *command; command++) 42655849Syokota err = serio_write(serio, *command); 42716565Ssos 42816565Ssos return err; 42916565Ssos} 43016565Ssos 43116565Ssosstatic int wacom_send_setup_string(struct wacom *wacom, struct serio *serio) 43216565Ssos{ 43316565Ssos const u8 *cmd; 43416565Ssos 43516565Ssos switch (wacom->dev->id.version) { 43630764Scharnier case MODEL_CINTIQ: /* UNTESTED */ 43716565Ssos cmd = COMMAND_ORIGIN_IN_UPPER_LEFT 43816565Ssos COMMAND_TRANSMIT_AT_MAX_RATE 43916565Ssos COMMAND_ENABLE_CONTINUOUS_MODE 44016565Ssos COMMAND_START_SENDING_PACKETS; 44116565Ssos break; 44239287Ssos 44339287Ssos case MODEL_PENPARTNER: 44439287Ssos cmd = COMMAND_ENABLE_PRESSURE_MODE 44539287Ssos COMMAND_START_SENDING_PACKETS; 44639287Ssos break; 44739287Ssos 44839287Ssos default: 44939287Ssos cmd = COMMAND_MULTI_MODE_INPUT 45039287Ssos COMMAND_ORIGIN_IN_UPPER_LEFT 45139287Ssos COMMAND_ENABLE_ALL_MACRO_BUTTONS 45239287Ssos COMMAND_DISABLE_GROUP_1_MACRO_BUTTONS 45339287Ssos COMMAND_TRANSMIT_AT_MAX_RATE 45439287Ssos COMMAND_DISABLE_INCREMENTAL_MODE 45548105Syokota COMMAND_ENABLE_CONTINUOUS_MODE 45639287Ssos COMMAND_Z_FILTER 45739287Ssos COMMAND_START_SENDING_PACKETS; 45839287Ssos break; 45939287Ssos } 46039287Ssos 46139287Ssos return wacom_send(serio, cmd); 46239287Ssos} 46339287Ssos 46439287Ssosstatic int wacom_send_and_wait(struct wacom *wacom, struct serio *serio, 46539287Ssos const u8 *cmd, const char *desc) 46623457Sbrian{ 46739287Ssos int err; 46839287Ssos unsigned long u; 46942505Syokota 47039287Ssos wacom->expect = cmd[1]; 47139287Ssos init_completion(&wacom->cmd_done); 47239287Ssos 47339287Ssos err = wacom_send(serio, cmd); 47439287Ssos if (err) 47539287Ssos return err; 47639287Ssos 47742505Syokota u = wait_for_completion_timeout(&wacom->cmd_done, HZ); 47842505Syokota if (u == 0) { 47942505Syokota /* Timeout, process what we've received. */ 48039287Ssos wacom_handle_response(wacom); 48142505Syokota } 48239287Ssos 48339287Ssos wacom->expect = 0; 48448105Syokota return wacom->result; 48548105Syokota} 48648105Syokota 48748105Syokotastatic int wacom_setup(struct wacom *wacom, struct serio *serio) 48848105Syokota{ 48948105Syokota int err; 49048105Syokota 49139287Ssos /* Note that setting the link speed is the job of inputattach. 49239287Ssos * We assume that reset negotiation has already happened, 49339287Ssos * here. */ 49439287Ssos err = wacom_send_and_wait(wacom, serio, REQUEST_MODEL_AND_ROM_VERSION, 49539287Ssos "model and version"); 49639287Ssos if (err) 49739287Ssos return err; 49839287Ssos 49939287Ssos if (!(wacom->res_x && wacom->res_y)) { 50039287Ssos err = wacom_send_and_wait(wacom, serio, 50139287Ssos REQUEST_CONFIGURATION_STRING, 50239287Ssos "configuration string"); 50339287Ssos if (err) 50439287Ssos return err; 50539287Ssos } 50639287Ssos 50739287Ssos if (!(wacom->max_x && wacom->max_y)) { 50839287Ssos err = wacom_send_and_wait(wacom, serio, 50948105Syokota REQUEST_MAX_COORDINATES, 51048105Syokota "coordinates string"); 51139287Ssos if (err) 51239287Ssos return err; 51339287Ssos } 51439287Ssos 51539287Ssos return wacom_send_setup_string(wacom, serio); 51639287Ssos} 51739287Ssos 51839287Ssosstatic int wacom_connect(struct serio *serio, struct serio_driver *drv) 51939287Ssos{ 52039287Ssos struct wacom *wacom; 52139287Ssos struct input_dev *input_dev; 52239287Ssos int err = -ENOMEM; 52339287Ssos 52439287Ssos wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); 52539287Ssos input_dev = input_allocate_device(); 52639287Ssos if (!wacom || !input_dev) 52739287Ssos goto free_device; 52839287Ssos 52943186Sdfr wacom->dev = input_dev; 53043186Sdfr wacom->extra_z_bits = 1; 53148105Syokota wacom->eraser_mask = 0x04; 53243186Sdfr wacom->tool = wacom->idx = 0; 53339287Ssos snprintf(wacom->phys, sizeof(wacom->phys), "%s/input0", serio->phys); 53439287Ssos input_dev->phys = wacom->phys; 53539287Ssos input_dev->id.bustype = BUS_RS232; 53639287Ssos input_dev->id.vendor = SERIO_WACOM_IV; 53739287Ssos input_dev->id.product = serio->id.extra; 53839287Ssos input_dev->dev.parent = &serio->dev; 53939287Ssos 54039287Ssos input_dev->evbit[0] = 54139287Ssos BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) | BIT_MASK(EV_REL); 54239287Ssos set_bit(ABS_MISC, input_dev->absbit); 54339287Ssos set_bit(BTN_TOOL_PEN, input_dev->keybit); 54439287Ssos set_bit(BTN_TOOL_RUBBER, input_dev->keybit); 54539287Ssos set_bit(BTN_TOOL_MOUSE, input_dev->keybit); 54639287Ssos set_bit(BTN_TOUCH, input_dev->keybit); 54739287Ssos set_bit(BTN_STYLUS, input_dev->keybit); 54839287Ssos set_bit(BTN_LEFT, input_dev->keybit); 54939287Ssos set_bit(BTN_RIGHT, input_dev->keybit); 5502089Ssos set_bit(BTN_MIDDLE, input_dev->keybit); 5512089Ssos 5522089Ssos serio_set_drvdata(serio, wacom); 5532089Ssos 5542089Ssos err = serio_open(serio, drv); 5552089Ssos if (err) 5562089Ssos goto free_device; 5572089Ssos 5582089Ssos err = wacom_setup(wacom, serio); 5598857Srgrimes if (err) 5608857Srgrimes goto close_serio; 5612089Ssos 5622089Ssos set_bit(INPUT_PROP_DIRECT, input_dev->propbit); 5638857Srgrimes if (!(wacom->flags & F_COVERS_SCREEN)) 5642089Ssos __set_bit(INPUT_PROP_POINTER, input_dev->propbit); 5652089Ssos 5662089Ssos if (wacom->flags & F_HAS_STYLUS2) 56723457Sbrian __set_bit(BTN_STYLUS2, input_dev->keybit); 5682089Ssos 5692089Ssos if (wacom->flags & F_HAS_SCROLLWHEEL) 5702089Ssos __set_bit(REL_WHEEL, input_dev->relbit); 5712089Ssos 5728857Srgrimes input_abs_set_res(wacom->dev, ABS_X, wacom->res_x); 5732089Ssos input_abs_set_res(wacom->dev, ABS_Y, wacom->res_y); 57430764Scharnier input_set_abs_params(wacom->dev, ABS_X, 0, wacom->max_x, 0, 0); 57530764Scharnier input_set_abs_params(wacom->dev, ABS_Y, 0, wacom->max_y, 0, 0); 57655849Syokota input_set_abs_params(wacom->dev, ABS_PRESSURE, -1, 5772089Ssos (1 << (7 + wacom->extra_z_bits)) - 1, 0, 0); 57816565Ssos 57916565Ssos err = input_register_device(wacom->dev); 58016565Ssos if (err) 5812089Ssos goto close_serio; 5825536Ssos 5832089Ssos return 0; 5842089Ssos 5852089Ssosclose_serio: 5862089Ssos serio_close(serio); 5872089Ssosfree_device: 5882089Ssos serio_set_drvdata(serio, NULL); 5892089Ssos input_free_device(input_dev); 5902089Ssos kfree(wacom); 59139287Ssos return err; 59239287Ssos} 59339287Ssos 5942089Ssosstatic const struct serio_device_id wacom_serio_ids[] = { 5952089Ssos { 5962089Ssos .type = SERIO_RS232, 5972089Ssos .proto = SERIO_WACOM_IV, 5982089Ssos .id = SERIO_ANY, 5992089Ssos .extra = SERIO_ANY, 60055849Syokota }, 60155849Syokota { 0 } 60255849Syokota}; 60316565Ssos 60416565SsosMODULE_DEVICE_TABLE(serio, wacom_serio_ids); 60516565Ssos 6062089Ssosstatic struct serio_driver wacom_drv = { 6072089Ssos .driver = { 6082089Ssos .name = "wacom_serial4", 60923457Sbrian }, 61023457Sbrian .description = "Wacom protocol 4 serial tablet driver", 61123457Sbrian .id_table = wacom_serio_ids, 6122089Ssos .interrupt = wacom_interrupt, 6132089Ssos .connect = wacom_connect, 6142089Ssos .disconnect = wacom_disconnect, 6152089Ssos}; 6162089Ssos 6172089Ssosmodule_serio_driver(wacom_drv); 6182089Ssos