0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/errno.h>
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/slab.h>
0017 #include <linux/input.h>
0018 #include <linux/serio.h>
0019
0020 #define DRIVER_DESC "EETI Egalax serial touchscreen driver"
0021
0022
0023
0024
0025
0026 #define EGALAX_FORMAT_MAX_LENGTH 6
0027 #define EGALAX_FORMAT_START_BIT BIT(7)
0028 #define EGALAX_FORMAT_PRESSURE_BIT BIT(6)
0029 #define EGALAX_FORMAT_TOUCH_BIT BIT(0)
0030 #define EGALAX_FORMAT_RESOLUTION_MASK 0x06
0031
0032 #define EGALAX_MIN_XC 0
0033 #define EGALAX_MAX_XC 0x4000
0034 #define EGALAX_MIN_YC 0
0035 #define EGALAX_MAX_YC 0x4000
0036
0037
0038
0039
0040 struct egalax {
0041 struct input_dev *input;
0042 struct serio *serio;
0043 int idx;
0044 u8 data[EGALAX_FORMAT_MAX_LENGTH];
0045 char phys[32];
0046 };
0047
0048 static void egalax_process_data(struct egalax *egalax)
0049 {
0050 struct input_dev *dev = egalax->input;
0051 u8 *data = egalax->data;
0052 u16 x, y;
0053 u8 shift;
0054 u8 mask;
0055
0056 shift = 3 - ((data[0] & EGALAX_FORMAT_RESOLUTION_MASK) >> 1);
0057 mask = 0xff >> (shift + 1);
0058
0059 x = (((u16)(data[1] & mask) << 7) | (data[2] & 0x7f)) << shift;
0060 y = (((u16)(data[3] & mask) << 7) | (data[4] & 0x7f)) << shift;
0061
0062 input_report_key(dev, BTN_TOUCH, data[0] & EGALAX_FORMAT_TOUCH_BIT);
0063 input_report_abs(dev, ABS_X, x);
0064 input_report_abs(dev, ABS_Y, y);
0065 input_sync(dev);
0066 }
0067
0068 static irqreturn_t egalax_interrupt(struct serio *serio,
0069 unsigned char data, unsigned int flags)
0070 {
0071 struct egalax *egalax = serio_get_drvdata(serio);
0072 int pkt_len;
0073
0074 egalax->data[egalax->idx++] = data;
0075
0076 if (likely(egalax->data[0] & EGALAX_FORMAT_START_BIT)) {
0077 pkt_len = egalax->data[0] & EGALAX_FORMAT_PRESSURE_BIT ? 6 : 5;
0078 if (pkt_len == egalax->idx) {
0079 egalax_process_data(egalax);
0080 egalax->idx = 0;
0081 }
0082 } else {
0083 dev_dbg(&serio->dev, "unknown/unsynchronized data: %x\n",
0084 egalax->data[0]);
0085 egalax->idx = 0;
0086 }
0087
0088 return IRQ_HANDLED;
0089 }
0090
0091
0092
0093
0094
0095
0096 static int egalax_connect(struct serio *serio, struct serio_driver *drv)
0097 {
0098 struct egalax *egalax;
0099 struct input_dev *input_dev;
0100 int error;
0101
0102 egalax = kzalloc(sizeof(struct egalax), GFP_KERNEL);
0103 input_dev = input_allocate_device();
0104 if (!egalax || !input_dev) {
0105 error = -ENOMEM;
0106 goto err_free_mem;
0107 }
0108
0109 egalax->serio = serio;
0110 egalax->input = input_dev;
0111 snprintf(egalax->phys, sizeof(egalax->phys),
0112 "%s/input0", serio->phys);
0113
0114 input_dev->name = "EETI eGalaxTouch Serial TouchScreen";
0115 input_dev->phys = egalax->phys;
0116 input_dev->id.bustype = BUS_RS232;
0117 input_dev->id.vendor = SERIO_EGALAX;
0118 input_dev->id.product = 0;
0119 input_dev->id.version = 0x0001;
0120 input_dev->dev.parent = &serio->dev;
0121
0122 input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
0123 input_set_abs_params(input_dev, ABS_X,
0124 EGALAX_MIN_XC, EGALAX_MAX_XC, 0, 0);
0125 input_set_abs_params(input_dev, ABS_Y,
0126 EGALAX_MIN_YC, EGALAX_MAX_YC, 0, 0);
0127
0128 serio_set_drvdata(serio, egalax);
0129
0130 error = serio_open(serio, drv);
0131 if (error)
0132 goto err_reset_drvdata;
0133
0134 error = input_register_device(input_dev);
0135 if (error)
0136 goto err_close_serio;
0137
0138 return 0;
0139
0140 err_close_serio:
0141 serio_close(serio);
0142 err_reset_drvdata:
0143 serio_set_drvdata(serio, NULL);
0144 err_free_mem:
0145 input_free_device(input_dev);
0146 kfree(egalax);
0147 return error;
0148 }
0149
0150 static void egalax_disconnect(struct serio *serio)
0151 {
0152 struct egalax *egalax = serio_get_drvdata(serio);
0153
0154 serio_close(serio);
0155 serio_set_drvdata(serio, NULL);
0156 input_unregister_device(egalax->input);
0157 kfree(egalax);
0158 }
0159
0160
0161
0162
0163
0164 static const struct serio_device_id egalax_serio_ids[] = {
0165 {
0166 .type = SERIO_RS232,
0167 .proto = SERIO_EGALAX,
0168 .id = SERIO_ANY,
0169 .extra = SERIO_ANY,
0170 },
0171 { 0 }
0172 };
0173
0174 MODULE_DEVICE_TABLE(serio, egalax_serio_ids);
0175
0176 static struct serio_driver egalax_drv = {
0177 .driver = {
0178 .name = "egalax",
0179 },
0180 .description = DRIVER_DESC,
0181 .id_table = egalax_serio_ids,
0182 .interrupt = egalax_interrupt,
0183 .connect = egalax_connect,
0184 .disconnect = egalax_disconnect,
0185 };
0186 module_serio_driver(egalax_drv);
0187
0188 MODULE_AUTHOR("Zoltán Böszörményi <zboszor@pr.hu>");
0189 MODULE_DESCRIPTION(DRIVER_DESC);
0190 MODULE_LICENSE("GPL v2");