exc3000.c (62b31a045757eac81fed94b19df47418a0818528) exc3000.c (a63d0120a2dd89eabf24b415b27208e190e989b0)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Driver for I2C connected EETI EXC3000 multiple touch controller
4 *
5 * Copyright (C) 2017 Ahmet Inan <inan@distec.de>
6 *
7 * minimal implementation based on egalax_ts.c and egalax_i2c.c
8 */

--- 16 unchanged lines hidden (view full) ---

25#define EXC3000_NUM_SLOTS 10
26#define EXC3000_SLOTS_PER_FRAME 5
27#define EXC3000_LEN_FRAME 66
28#define EXC3000_LEN_POINT 10
29
30#define EXC3000_LEN_MODEL_NAME 16
31#define EXC3000_LEN_FW_VERSION 16
32
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Driver for I2C connected EETI EXC3000 multiple touch controller
4 *
5 * Copyright (C) 2017 Ahmet Inan <inan@distec.de>
6 *
7 * minimal implementation based on egalax_ts.c and egalax_i2c.c
8 */

--- 16 unchanged lines hidden (view full) ---

25#define EXC3000_NUM_SLOTS 10
26#define EXC3000_SLOTS_PER_FRAME 5
27#define EXC3000_LEN_FRAME 66
28#define EXC3000_LEN_POINT 10
29
30#define EXC3000_LEN_MODEL_NAME 16
31#define EXC3000_LEN_FW_VERSION 16
32
33#define EXC3000_VENDOR_EVENT 0x03
33#define EXC3000_MT1_EVENT 0x06
34#define EXC3000_MT2_EVENT 0x18
35
36#define EXC3000_TIMEOUT_MS 100
37
38#define EXC3000_RESET_MS 10
39#define EXC3000_READY_MS 100
40

--- 59 unchanged lines hidden (view full) ---

100static void exc3000_timer(struct timer_list *t)
101{
102 struct exc3000_data *data = from_timer(data, t, timer);
103
104 input_mt_sync_frame(data->input);
105 input_sync(data->input);
106}
107
34#define EXC3000_MT1_EVENT 0x06
35#define EXC3000_MT2_EVENT 0x18
36
37#define EXC3000_TIMEOUT_MS 100
38
39#define EXC3000_RESET_MS 10
40#define EXC3000_READY_MS 100
41

--- 59 unchanged lines hidden (view full) ---

101static void exc3000_timer(struct timer_list *t)
102{
103 struct exc3000_data *data = from_timer(data, t, timer);
104
105 input_mt_sync_frame(data->input);
106 input_sync(data->input);
107}
108
109static inline void exc3000_schedule_timer(struct exc3000_data *data)
110{
111 mod_timer(&data->timer, jiffies + msecs_to_jiffies(EXC3000_TIMEOUT_MS));
112}
113
108static int exc3000_read_frame(struct exc3000_data *data, u8 *buf)
109{
110 struct i2c_client *client = data->client;
114static int exc3000_read_frame(struct exc3000_data *data, u8 *buf)
115{
116 struct i2c_client *client = data->client;
111 u8 expected_event = EXC3000_MT1_EVENT;
112 int ret;
113
117 int ret;
118
114 if (data->info->max_xy == SZ_16K - 1)
115 expected_event = EXC3000_MT2_EVENT;
116
117 ret = i2c_master_send(client, "'", 2);
118 if (ret < 0)
119 return ret;
120
121 if (ret != 2)
122 return -EIO;
123
124 ret = i2c_master_recv(client, buf, EXC3000_LEN_FRAME);
125 if (ret < 0)
126 return ret;
127
128 if (ret != EXC3000_LEN_FRAME)
129 return -EIO;
130
131 if (get_unaligned_le16(buf) != EXC3000_LEN_FRAME)
132 return -EINVAL;
133
119 ret = i2c_master_send(client, "'", 2);
120 if (ret < 0)
121 return ret;
122
123 if (ret != 2)
124 return -EIO;
125
126 ret = i2c_master_recv(client, buf, EXC3000_LEN_FRAME);
127 if (ret < 0)
128 return ret;
129
130 if (ret != EXC3000_LEN_FRAME)
131 return -EIO;
132
133 if (get_unaligned_le16(buf) != EXC3000_LEN_FRAME)
134 return -EINVAL;
135
134 if (buf[2] != expected_event)
135 return -EINVAL;
136
137 return 0;
138}
139
136 return 0;
137}
138
140static int exc3000_read_data(struct exc3000_data *data,
141 u8 *buf, int *n_slots)
139static int exc3000_handle_mt_event(struct exc3000_data *data)
142{
140{
143 int error;
141 struct input_dev *input = data->input;
142 int ret, total_slots;
143 u8 *buf = data->buf;
144
144
145 error = exc3000_read_frame(data, buf);
146 if (error)
147 return error;
145 total_slots = buf[3];
146 if (!total_slots || total_slots > EXC3000_NUM_SLOTS) {
147 ret = -EINVAL;
148 goto out_fail;
149 }
148
150
149 *n_slots = buf[3];
150 if (!*n_slots || *n_slots > EXC3000_NUM_SLOTS)
151 return -EINVAL;
152
153 if (*n_slots > EXC3000_SLOTS_PER_FRAME) {
151 if (total_slots > EXC3000_SLOTS_PER_FRAME) {
154 /* Read 2nd frame to get the rest of the contacts. */
152 /* Read 2nd frame to get the rest of the contacts. */
155 error = exc3000_read_frame(data, buf + EXC3000_LEN_FRAME);
156 if (error)
157 return error;
153 ret = exc3000_read_frame(data, buf + EXC3000_LEN_FRAME);
154 if (ret)
155 goto out_fail;
158
159 /* 2nd chunk must have number of contacts set to 0. */
156
157 /* 2nd chunk must have number of contacts set to 0. */
160 if (buf[EXC3000_LEN_FRAME + 3] != 0)
161 return -EINVAL;
158 if (buf[EXC3000_LEN_FRAME + 3] != 0) {
159 ret = -EINVAL;
160 goto out_fail;
161 }
162 }
163
162 }
163
164 /*
165 * We read full state successfully, no contacts will be "stuck".
166 */
167 del_timer_sync(&data->timer);
168
169 while (total_slots > 0) {
170 int slots = min(total_slots, EXC3000_SLOTS_PER_FRAME);
171
172 exc3000_report_slots(input, &data->prop, buf + 4, slots);
173 total_slots -= slots;
174 buf += EXC3000_LEN_FRAME;
175 }
176
177 input_mt_sync_frame(input);
178 input_sync(input);
179
164 return 0;
180 return 0;
181
182out_fail:
183 /* Schedule a timer to release "stuck" contacts */
184 exc3000_schedule_timer(data);
185
186 return ret;
165}
166
167static int exc3000_query_interrupt(struct exc3000_data *data)
168{
169 u8 *buf = data->buf;
187}
188
189static int exc3000_query_interrupt(struct exc3000_data *data)
190{
191 u8 *buf = data->buf;
170 int error;
171
192
172 error = i2c_master_recv(data->client, buf, EXC3000_LEN_FRAME);
173 if (error < 0)
174 return error;
175
176 if (buf[0] != 'B')
177 return -EPROTO;
178
179 if (buf[4] == 'E')
180 strlcpy(data->model, buf + 5, sizeof(data->model));
181 else if (buf[4] == 'D')
182 strlcpy(data->fw_version, buf + 5, sizeof(data->fw_version));
183 else
184 return -EPROTO;
185
186 return 0;
187}
188
189static irqreturn_t exc3000_interrupt(int irq, void *dev_id)
190{
191 struct exc3000_data *data = dev_id;
193 if (buf[0] != 'B')
194 return -EPROTO;
195
196 if (buf[4] == 'E')
197 strlcpy(data->model, buf + 5, sizeof(data->model));
198 else if (buf[4] == 'D')
199 strlcpy(data->fw_version, buf + 5, sizeof(data->fw_version));
200 else
201 return -EPROTO;
202
203 return 0;
204}
205
206static irqreturn_t exc3000_interrupt(int irq, void *dev_id)
207{
208 struct exc3000_data *data = dev_id;
192 struct input_dev *input = data->input;
193 u8 *buf = data->buf;
209 u8 *buf = data->buf;
194 int slots, total_slots;
195 int error;
210 int ret;
196
211
197 if (mutex_is_locked(&data->query_lock)) {
198 data->query_result = exc3000_query_interrupt(data);
199 complete(&data->wait_event);
200 goto out;
201 }
202
203 error = exc3000_read_data(data, buf, &total_slots);
204 if (error) {
212 ret = exc3000_read_frame(data, buf);
213 if (ret) {
205 /* Schedule a timer to release "stuck" contacts */
214 /* Schedule a timer to release "stuck" contacts */
206 mod_timer(&data->timer,
207 jiffies + msecs_to_jiffies(EXC3000_TIMEOUT_MS));
215 exc3000_schedule_timer(data);
208 goto out;
209 }
210
216 goto out;
217 }
218
211 /*
212 * We read full state successfully, no contacts will be "stuck".
213 */
214 del_timer_sync(&data->timer);
219 switch (buf[2]) {
220 case EXC3000_VENDOR_EVENT:
221 data->query_result = exc3000_query_interrupt(data);
222 complete(&data->wait_event);
223 break;
215
224
216 while (total_slots > 0) {
217 slots = min(total_slots, EXC3000_SLOTS_PER_FRAME);
218 exc3000_report_slots(input, &data->prop, buf + 4, slots);
219 total_slots -= slots;
220 buf += EXC3000_LEN_FRAME;
225 case EXC3000_MT1_EVENT:
226 case EXC3000_MT2_EVENT:
227 exc3000_handle_mt_event(data);
228 break;
229
230 default:
231 break;
221 }
222
232 }
233
223 input_mt_sync_frame(input);
224 input_sync(input);
225
226out:
227 return IRQ_HANDLED;
228}
229
230static ssize_t fw_version_show(struct device *dev,
231 struct device_attribute *attr, char *buf)
232{
233 struct i2c_client *client = to_i2c_client(dev);

--- 201 unchanged lines hidden ---
234out:
235 return IRQ_HANDLED;
236}
237
238static ssize_t fw_version_show(struct device *dev,
239 struct device_attribute *attr, char *buf)
240{
241 struct i2c_client *client = to_i2c_client(dev);

--- 201 unchanged lines hidden ---