27
27
#define EXC3000_LEN_FRAME 66
28
28
#define EXC3000_LEN_POINT 10
29
29
30
+ #define EXC3000_LEN_MODEL_NAME 16
31
+ #define EXC3000_LEN_FW_VERSION 16
32
+
30
33
#define EXC3000_MT1_EVENT 0x06
31
34
#define EXC3000_MT2_EVENT 0x18
32
35
@@ -71,6 +74,11 @@ struct exc3000_data {
71
74
struct gpio_desc * reset ;
72
75
struct timer_list timer ;
73
76
u8 buf [2 * EXC3000_LEN_FRAME ];
77
+ struct completion wait_event ;
78
+ struct mutex query_lock ;
79
+ int query_result ;
80
+ char model [EXC3000_LEN_MODEL_NAME ];
81
+ char fw_version [EXC3000_LEN_FW_VERSION ];
74
82
};
75
83
76
84
static void exc3000_report_slots (struct input_dev * input ,
@@ -156,6 +164,28 @@ static int exc3000_read_data(struct exc3000_data *data,
156
164
return 0 ;
157
165
}
158
166
167
+ static int exc3000_query_interrupt (struct exc3000_data * data )
168
+ {
169
+ u8 * buf = data -> buf ;
170
+ int error ;
171
+
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
+
159
189
static irqreturn_t exc3000_interrupt (int irq , void * dev_id )
160
190
{
161
191
struct exc3000_data * data = dev_id ;
@@ -164,6 +194,12 @@ static irqreturn_t exc3000_interrupt(int irq, void *dev_id)
164
194
int slots , total_slots ;
165
195
int error ;
166
196
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
+
167
203
error = exc3000_read_data (data , buf , & total_slots );
168
204
if (error ) {
169
205
/* Schedule a timer to release "stuck" contacts */
@@ -191,11 +227,91 @@ static irqreturn_t exc3000_interrupt(int irq, void *dev_id)
191
227
return IRQ_HANDLED ;
192
228
}
193
229
230
+ static 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 );
234
+ struct exc3000_data * data = i2c_get_clientdata (client );
235
+ static const u8 request [68 ] = {
236
+ 0x67 , 0x00 , 0x42 , 0x00 , 0x03 , 0x01 , 'D' , 0x00
237
+ };
238
+ int error ;
239
+
240
+ mutex_lock (& data -> query_lock );
241
+
242
+ data -> query_result = - ETIMEDOUT ;
243
+ reinit_completion (& data -> wait_event );
244
+
245
+ error = i2c_master_send (client , request , sizeof (request ));
246
+ if (error < 0 ) {
247
+ mutex_unlock (& data -> query_lock );
248
+ return error ;
249
+ }
250
+
251
+ wait_for_completion_interruptible_timeout (& data -> wait_event , 1 * HZ );
252
+ mutex_unlock (& data -> query_lock );
253
+
254
+ if (data -> query_result < 0 )
255
+ return data -> query_result ;
256
+
257
+ return sprintf (buf , "%s\n" , data -> fw_version );
258
+ }
259
+ static DEVICE_ATTR_RO (fw_version );
260
+
261
+ static ssize_t exc3000_get_model (struct exc3000_data * data )
262
+ {
263
+ static const u8 request [68 ] = {
264
+ 0x67 , 0x00 , 0x42 , 0x00 , 0x03 , 0x01 , 'E' , 0x00
265
+ };
266
+ struct i2c_client * client = data -> client ;
267
+ int error ;
268
+
269
+ mutex_lock (& data -> query_lock );
270
+ data -> query_result = - ETIMEDOUT ;
271
+ reinit_completion (& data -> wait_event );
272
+
273
+ error = i2c_master_send (client , request , sizeof (request ));
274
+ if (error < 0 ) {
275
+ mutex_unlock (& data -> query_lock );
276
+ return error ;
277
+ }
278
+
279
+ wait_for_completion_interruptible_timeout (& data -> wait_event , 1 * HZ );
280
+ mutex_unlock (& data -> query_lock );
281
+
282
+ return data -> query_result ;
283
+ }
284
+
285
+ static ssize_t model_show (struct device * dev ,
286
+ struct device_attribute * attr , char * buf )
287
+ {
288
+ struct i2c_client * client = to_i2c_client (dev );
289
+ struct exc3000_data * data = i2c_get_clientdata (client );
290
+ int error ;
291
+
292
+ error = exc3000_get_model (data );
293
+ if (error < 0 )
294
+ return error ;
295
+
296
+ return sprintf (buf , "%s\n" , data -> model );
297
+ }
298
+ static DEVICE_ATTR_RO (model );
299
+
300
+ static struct attribute * sysfs_attrs [] = {
301
+ & dev_attr_fw_version .attr ,
302
+ & dev_attr_model .attr ,
303
+ NULL
304
+ };
305
+
306
+ static struct attribute_group exc3000_attribute_group = {
307
+ .attrs = sysfs_attrs
308
+ };
309
+
194
310
static int exc3000_probe (struct i2c_client * client )
195
311
{
196
312
struct exc3000_data * data ;
197
313
struct input_dev * input ;
198
- int error , max_xy ;
314
+ int error , max_xy , retry ;
199
315
200
316
data = devm_kzalloc (& client -> dev , sizeof (* data ), GFP_KERNEL );
201
317
if (!data )
@@ -209,6 +325,8 @@ static int exc3000_probe(struct i2c_client *client)
209
325
data -> info = & exc3000_info [eeti_dev_id ];
210
326
}
211
327
timer_setup (& data -> timer , exc3000_timer , 0 );
328
+ init_completion (& data -> wait_event );
329
+ mutex_init (& data -> query_lock );
212
330
213
331
data -> reset = devm_gpiod_get_optional (& client -> dev , "reset" ,
214
332
GPIOD_OUT_HIGH );
@@ -226,6 +344,7 @@ static int exc3000_probe(struct i2c_client *client)
226
344
return - ENOMEM ;
227
345
228
346
data -> input = input ;
347
+ input_set_drvdata (input , data );
229
348
230
349
input -> name = data -> info -> name ;
231
350
input -> id .bustype = BUS_I2C ;
@@ -251,6 +370,33 @@ static int exc3000_probe(struct i2c_client *client)
251
370
if (error )
252
371
return error ;
253
372
373
+ /*
374
+ * I²C does not have built-in recovery, so retry on failure. This
375
+ * ensures, that the device probe will not fail for temporary issues
376
+ * on the bus. This is not needed for the sysfs calls (userspace
377
+ * will receive the error code and can start another query) and
378
+ * cannot be done for touch events (but that only means loosing one
379
+ * or two touch events anyways).
380
+ */
381
+ for (retry = 0 ; retry < 3 ; retry ++ ) {
382
+ error = exc3000_get_model (data );
383
+ if (!error )
384
+ break ;
385
+ dev_warn (& client -> dev , "Retry %d get EETI EXC3000 model: %d\n" ,
386
+ retry + 1 , error );
387
+ }
388
+
389
+ if (error )
390
+ return error ;
391
+
392
+ dev_dbg (& client -> dev , "TS Model: %s" , data -> model );
393
+
394
+ i2c_set_clientdata (client , data );
395
+
396
+ error = devm_device_add_group (& client -> dev , & exc3000_attribute_group );
397
+ if (error )
398
+ return error ;
399
+
254
400
return 0 ;
255
401
}
256
402
0 commit comments