1 // SPDX-License-Identifier: GPL-2.0-only
3 * Hampshire serial touchscreen driver
5 * Copyright (c) 2010 Adam Bennett
6 * Based on the dynapro driver (c) Tias Guns
11 * 2010/04/08 Adam Bennett <abennett72@gmail.com>
12 * Copied dynapro.c and edited for Hampshire 4-byte protocol
15 #include <linux/errno.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/slab.h>
19 #include <linux/input.h>
20 #include <linux/serio.h>
22 #define DRIVER_DESC "Hampshire serial touchscreen driver"
24 MODULE_AUTHOR("Adam Bennett <abennett72@gmail.com>");
25 MODULE_DESCRIPTION(DRIVER_DESC
);
26 MODULE_LICENSE("GPL");
29 * Definitions & global arrays.
32 #define HAMPSHIRE_FORMAT_TOUCH_BIT 0x40
33 #define HAMPSHIRE_FORMAT_LENGTH 4
34 #define HAMPSHIRE_RESPONSE_BEGIN_BYTE 0x80
36 #define HAMPSHIRE_MIN_XC 0
37 #define HAMPSHIRE_MAX_XC 0x1000
38 #define HAMPSHIRE_MIN_YC 0
39 #define HAMPSHIRE_MAX_YC 0x1000
41 #define HAMPSHIRE_GET_XC(data) (((data[3] & 0x0c) >> 2) | (data[1] << 2) | ((data[0] & 0x38) << 6))
42 #define HAMPSHIRE_GET_YC(data) ((data[3] & 0x03) | (data[2] << 2) | ((data[0] & 0x07) << 9))
43 #define HAMPSHIRE_GET_TOUCHED(data) (HAMPSHIRE_FORMAT_TOUCH_BIT & data[0])
46 * Per-touchscreen data.
50 struct input_dev
*dev
;
53 unsigned char data
[HAMPSHIRE_FORMAT_LENGTH
];
57 static void hampshire_process_data(struct hampshire
*phampshire
)
59 struct input_dev
*dev
= phampshire
->dev
;
61 if (HAMPSHIRE_FORMAT_LENGTH
== ++phampshire
->idx
) {
62 input_report_abs(dev
, ABS_X
, HAMPSHIRE_GET_XC(phampshire
->data
));
63 input_report_abs(dev
, ABS_Y
, HAMPSHIRE_GET_YC(phampshire
->data
));
64 input_report_key(dev
, BTN_TOUCH
,
65 HAMPSHIRE_GET_TOUCHED(phampshire
->data
));
72 static irqreturn_t
hampshire_interrupt(struct serio
*serio
,
73 unsigned char data
, unsigned int flags
)
75 struct hampshire
*phampshire
= serio_get_drvdata(serio
);
77 phampshire
->data
[phampshire
->idx
] = data
;
79 if (HAMPSHIRE_RESPONSE_BEGIN_BYTE
& phampshire
->data
[0])
80 hampshire_process_data(phampshire
);
82 dev_dbg(&serio
->dev
, "unknown/unsynchronized data: %x\n",
88 static void hampshire_disconnect(struct serio
*serio
)
90 struct hampshire
*phampshire
= serio_get_drvdata(serio
);
92 input_get_device(phampshire
->dev
);
93 input_unregister_device(phampshire
->dev
);
95 serio_set_drvdata(serio
, NULL
);
96 input_put_device(phampshire
->dev
);
101 * hampshire_connect() is the routine that is called when someone adds a
102 * new serio device that supports hampshire protocol and registers it as
103 * an input device. This is usually accomplished using inputattach.
106 static int hampshire_connect(struct serio
*serio
, struct serio_driver
*drv
)
108 struct hampshire
*phampshire
;
109 struct input_dev
*input_dev
;
112 phampshire
= kzalloc(sizeof(struct hampshire
), GFP_KERNEL
);
113 input_dev
= input_allocate_device();
114 if (!phampshire
|| !input_dev
) {
119 phampshire
->serio
= serio
;
120 phampshire
->dev
= input_dev
;
121 snprintf(phampshire
->phys
, sizeof(phampshire
->phys
),
122 "%s/input0", serio
->phys
);
124 input_dev
->name
= "Hampshire Serial TouchScreen";
125 input_dev
->phys
= phampshire
->phys
;
126 input_dev
->id
.bustype
= BUS_RS232
;
127 input_dev
->id
.vendor
= SERIO_HAMPSHIRE
;
128 input_dev
->id
.product
= 0;
129 input_dev
->id
.version
= 0x0001;
130 input_dev
->dev
.parent
= &serio
->dev
;
131 input_dev
->evbit
[0] = BIT_MASK(EV_KEY
) | BIT_MASK(EV_ABS
);
132 input_dev
->keybit
[BIT_WORD(BTN_TOUCH
)] = BIT_MASK(BTN_TOUCH
);
133 input_set_abs_params(phampshire
->dev
, ABS_X
,
134 HAMPSHIRE_MIN_XC
, HAMPSHIRE_MAX_XC
, 0, 0);
135 input_set_abs_params(phampshire
->dev
, ABS_Y
,
136 HAMPSHIRE_MIN_YC
, HAMPSHIRE_MAX_YC
, 0, 0);
138 serio_set_drvdata(serio
, phampshire
);
140 err
= serio_open(serio
, drv
);
144 err
= input_register_device(phampshire
->dev
);
150 fail3
: serio_close(serio
);
151 fail2
: serio_set_drvdata(serio
, NULL
);
152 fail1
: input_free_device(input_dev
);
158 * The serio driver structure.
161 static const struct serio_device_id hampshire_serio_ids
[] = {
164 .proto
= SERIO_HAMPSHIRE
,
171 MODULE_DEVICE_TABLE(serio
, hampshire_serio_ids
);
173 static struct serio_driver hampshire_drv
= {
177 .description
= DRIVER_DESC
,
178 .id_table
= hampshire_serio_ids
,
179 .interrupt
= hampshire_interrupt
,
180 .connect
= hampshire_connect
,
181 .disconnect
= hampshire_disconnect
,
184 module_serio_driver(hampshire_drv
);