1 /*
2 * Copyright 2020, Jérôme Duval, jerome.duval@gmail.com.
3 * Copyright 2008-2011 Michael Lotz <mmlr@mlotz.ch>
4 * Copyright 2020, 2022 Vladimir Kondratyev <wulf@FreeBSD.org>
5 * Copyright 2023 Vladimir Serbinenko <phcoder@gmail.com>
6 * Distributed under the terms of the MIT license.
7 */
8
9
10 //! Driver for I2C Elan Devices.
11 // Partially based on FreeBSD ietp driver
12
13
14 #include <ACPI.h>
15 #include <device_manager.h>
16 #include <i2c.h>
17
18 #include "DeviceList.h"
19 #include "Driver.h"
20 #include "ELANDevice.h"
21
22 #include <lock.h>
23 #include <util/AutoLock.h>
24
25 #include <new>
26 #include <stdio.h>
27 #include <string.h>
28
29
30
31 struct elan_driver_cookie {
32 ELANDevice* elanDevice;
33 };
34
35 #define I2C_ELAN_DRIVER_NAME "drivers/input/i2c_elan/driver_v1"
36 #define I2C_ELAN_DEVICE_NAME "drivers/input/i2c_elan/device_v1"
37
38 /* Base Namespace devices are published to */
39 #define I2C_ELAN_BASENAME "input/i2c_elan/%d"
40
41 static const char* elan_iic_devs[] = {
42 "ELAN0000",
43 "ELAN0100",
44 "ELAN0600",
45 "ELAN0601",
46 "ELAN0602",
47 "ELAN0603",
48 "ELAN0604",
49 "ELAN0605",
50 "ELAN0606",
51 "ELAN0607",
52 "ELAN0608",
53 "ELAN0609",
54 "ELAN060B",
55 "ELAN060C",
56 "ELAN060F",
57 "ELAN0610",
58 "ELAN0611",
59 "ELAN0612",
60 "ELAN0615",
61 "ELAN0616",
62 "ELAN0617",
63 "ELAN0618",
64 "ELAN0619",
65 "ELAN061A",
66 "ELAN061B",
67 "ELAN061C",
68 "ELAN061D",
69 "ELAN061E",
70 "ELAN061F",
71 "ELAN0620",
72 "ELAN0621",
73 "ELAN0622",
74 "ELAN0623",
75 "ELAN0624",
76 "ELAN0625",
77 "ELAN0626",
78 "ELAN0627",
79 "ELAN0628",
80 "ELAN0629",
81 "ELAN062A",
82 "ELAN062B",
83 "ELAN062C",
84 "ELAN062D",
85 "ELAN062E", /* Lenovo V340 Whiskey Lake U */
86 "ELAN062F", /* Lenovo V340 Comet Lake U */
87 "ELAN0631",
88 "ELAN0632",
89 "ELAN0633", /* Lenovo S145 */
90 "ELAN0634", /* Lenovo V340 Ice lake */
91 "ELAN0635", /* Lenovo V1415-IIL */
92 "ELAN0636", /* Lenovo V1415-Dali */
93 "ELAN0637", /* Lenovo V1415-IGLR */
94 "ELAN1000"
95 };
96
97 static device_manager_info *sDeviceManager;
98
99 DeviceList *gDeviceList = NULL;
100 static mutex sDriverLock;
101
102
103 // #pragma mark - driver hooks
104
105
106 static status_t
i2c_elan_init_device(void * driverCookie,void ** cookie)107 i2c_elan_init_device(void *driverCookie, void **cookie)
108 {
109 *cookie = driverCookie;
110 return B_OK;
111 }
112
113
114 static void
i2c_elan_uninit_device(void * _cookie)115 i2c_elan_uninit_device(void *_cookie)
116 {
117
118 }
119
120
121 static status_t
i2c_elan_open(void * initCookie,const char * path,int flags,void ** _cookie)122 i2c_elan_open(void *initCookie, const char *path, int flags, void **_cookie)
123 {
124 TRACE("open(%s, %" B_PRIu32 ", %p)\n", path, flags, _cookie);
125
126 elan_driver_cookie *cookie = new(std::nothrow) elan_driver_cookie();
127 if (cookie == NULL)
128 return B_NO_MEMORY;
129
130 MutexLocker locker(sDriverLock);
131
132 ELANDevice *elan = (ELANDevice *)gDeviceList->FindDevice(path);
133 TRACE(" path %s: handler %p (elan)\n", path, elan);
134
135 cookie->elanDevice = elan;
136
137 status_t result = elan == NULL ? B_ENTRY_NOT_FOUND : B_OK;
138 if (result == B_OK)
139 result = elan->Open(flags);
140
141 if (result != B_OK) {
142 delete cookie;
143 return result;
144 }
145
146 *_cookie = cookie;
147
148 return B_OK;
149 }
150
151
152 static status_t
i2c_elan_read(void * _cookie,off_t position,void * buffer,size_t * numBytes)153 i2c_elan_read(void *_cookie, off_t position, void *buffer, size_t *numBytes)
154 {
155 TRACE_ALWAYS("unhandled read on i2c_elan\n");
156 *numBytes = 0;
157 return B_ERROR;
158 }
159
160
161 static status_t
i2c_elan_write(void * _cookie,off_t position,const void * buffer,size_t * numBytes)162 i2c_elan_write(void *_cookie, off_t position, const void *buffer,
163 size_t *numBytes)
164 {
165 TRACE_ALWAYS("unhandled write on i2c_elan\n");
166 *numBytes = 0;
167 return B_ERROR;
168 }
169
170
171 static status_t
i2c_elan_control(void * _cookie,uint32 op,void * buffer,size_t length)172 i2c_elan_control(void *_cookie, uint32 op, void *buffer, size_t length)
173 {
174 elan_driver_cookie *cookie = (elan_driver_cookie *)_cookie;
175
176 TRACE("control(%p, %" B_PRIu32 ", %p, %" B_PRIuSIZE ")\n", cookie, op, buffer, length);
177 return cookie->elanDevice->Control(op, buffer, length);
178 }
179
180
181 static status_t
i2c_elan_close(void * _cookie)182 i2c_elan_close(void *_cookie)
183 {
184 elan_driver_cookie *cookie = (elan_driver_cookie *)_cookie;
185
186 TRACE("close(%p)\n", cookie);
187 return cookie->elanDevice->Close();
188 }
189
190
191 static status_t
i2c_elan_free(void * _cookie)192 i2c_elan_free(void *_cookie)
193 {
194 elan_driver_cookie *cookie = (elan_driver_cookie *)_cookie;
195 TRACE("free(%p)\n", cookie);
196
197 mutex_lock(&sDriverLock);
198
199 ELANDevice *device = cookie->elanDevice;
200 if (device->IsOpen()) {
201 // another handler of this device is still open so we can't free it
202 } else if (device->IsRemoved()) {
203 // the parent device is removed already and none of its handlers are
204 // open anymore so we can free it here
205 delete device;
206 }
207
208 mutex_unlock(&sDriverLock);
209
210 delete cookie;
211 return B_OK;
212 }
213
214
215 // #pragma mark - driver module API
216
is_elan_name(const char * name)217 static bool is_elan_name(const char *name) {
218 if (name == NULL)
219 return false;
220 for (unsigned i = 0; i < B_COUNT_OF(elan_iic_devs); i++)
221 if (strcmp(name, elan_iic_devs[i]) == 0)
222 return true;
223 return false;
224 };
225
226 static float
i2c_elan_support(device_node * parent)227 i2c_elan_support(device_node *parent)
228 {
229 CALLED();
230
231 // make sure parent is really the I2C bus manager
232 const char *bus;
233 if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
234 return -1;
235
236 if (strcmp(bus, "i2c"))
237 return 0.0;
238 TRACE("i2c_elan_support found an i2c device %p\n", parent);
239
240 // check whether it's an ELAN device
241 uint64 handlePointer;
242 if (sDeviceManager->get_attr_uint64(parent, ACPI_DEVICE_HANDLE_ITEM,
243 &handlePointer, false) != B_OK) {
244 TRACE("i2c_elan_support found an i2c device without acpi handle\n");
245 return B_ERROR;
246 }
247
248 const char *name = nullptr;
249 if (sDeviceManager->get_attr_string(parent, ACPI_DEVICE_HID_ITEM, &name,
250 false) == B_OK && is_elan_name(name)) {
251 TRACE("i2c_elan_support found an elan i2c device\n");
252 return 0.6;
253 }
254
255 if (sDeviceManager->get_attr_string(parent, ACPI_DEVICE_CID_ITEM, &name,
256 false) == B_OK && is_elan_name(name)) {
257 TRACE("i2c_elan_support found a compatible elan i2c device\n");
258 return 0.6;
259 }
260
261 return 0.0;
262 }
263
264 static status_t
i2c_elan_register_device(device_node * node)265 i2c_elan_register_device(device_node *node)
266 {
267 CALLED();
268
269 device_attr attrs[] = {
270 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = "I2C ELAN Device" }},
271 { NULL }
272 };
273
274 return sDeviceManager->register_node(node, I2C_ELAN_DRIVER_NAME, attrs,
275 NULL, NULL);
276 }
277
278
279 static status_t
i2c_elan_init_driver(device_node * node,void ** driverCookie)280 i2c_elan_init_driver(device_node *node, void **driverCookie)
281 {
282 CALLED();
283
284 elan_driver_cookie *device
285 = (elan_driver_cookie *)calloc(1, sizeof(elan_driver_cookie));
286 if (device == NULL)
287 return B_NO_MEMORY;
288
289 *driverCookie = device;
290
291 device_node *parent;
292 i2c_device_interface* i2c;
293 i2c_device i2c_cookie;
294
295 parent = sDeviceManager->get_parent_node(node);
296 sDeviceManager->get_driver(parent, (driver_module_info **)&i2c,
297 (void **)&i2c_cookie);
298 sDeviceManager->put_node(parent);
299
300 mutex_lock(&sDriverLock);
301 ELANDevice *elanDevice = new(std::nothrow) ELANDevice(node, i2c, i2c_cookie);
302
303 if (elanDevice != NULL && elanDevice->InitCheck() == B_OK) {
304 device->elanDevice = elanDevice;
305 } else
306 delete elanDevice;
307
308 mutex_unlock(&sDriverLock);
309
310 return device->elanDevice != NULL ? B_OK : B_IO_ERROR;
311 }
312
313
314 static void
i2c_elan_uninit_driver(void * driverCookie)315 i2c_elan_uninit_driver(void *driverCookie)
316 {
317 CALLED();
318 elan_driver_cookie *device = (elan_driver_cookie*)driverCookie;
319
320 free(device);
321 }
322
323
324 static status_t
i2c_elan_register_child_devices(void * cookie)325 i2c_elan_register_child_devices(void *cookie)
326 {
327 CALLED();
328 elan_driver_cookie *device = (elan_driver_cookie*)cookie;
329 ELANDevice* elanDevice = device->elanDevice;
330 if (elanDevice == NULL)
331 return B_OK;
332
333 // As devices can be un- and replugged at will, we cannot
334 // simply rely on a device count. If there is just one
335 // keyboard, this does not mean that it uses the 0 name.
336 // There might have been two keyboards and the one using 0
337 // might have been unplugged. So we just generate names
338 // until we find one that is not currently in use.
339 int32 index = 0;
340 char pathBuffer[128];
341 while (true) {
342 sprintf(pathBuffer, "input/mouse/" DEVICE_PATH_SUFFIX "/%" B_PRId32, index++);
343 if (gDeviceList->FindDevice(pathBuffer) == NULL) {
344 // this name is still free, use it
345 elanDevice->SetPublishPath(strdup(pathBuffer));
346 break;
347 }
348 }
349
350 gDeviceList->AddDevice(elanDevice->PublishPath(), elanDevice);
351
352 sDeviceManager->publish_device(device->elanDevice->Parent(), pathBuffer,
353 I2C_ELAN_DEVICE_NAME);
354
355 return B_OK;
356 }
357
358
359 static status_t
std_ops(int32 op,...)360 std_ops(int32 op, ...)
361 {
362 switch (op) {
363 case B_MODULE_INIT:
364 gDeviceList = new(std::nothrow) DeviceList();
365 if (gDeviceList == NULL) {
366 return B_NO_MEMORY;
367 }
368 mutex_init(&sDriverLock, "i2c elan driver lock");
369
370 return B_OK;
371 case B_MODULE_UNINIT:
372 delete gDeviceList;
373 gDeviceList = NULL;
374 mutex_destroy(&sDriverLock);
375 return B_OK;
376
377 default:
378 break;
379 }
380
381 return B_ERROR;
382 }
383
384
385 // #pragma mark -
386
387
388 driver_module_info i2c_elan_driver_module = {
389 {
390 I2C_ELAN_DRIVER_NAME,
391 0,
392 &std_ops
393 },
394
395 i2c_elan_support,
396 i2c_elan_register_device,
397 i2c_elan_init_driver,
398 i2c_elan_uninit_driver,
399 i2c_elan_register_child_devices,
400 NULL, // rescan
401 NULL, // removed
402 };
403
404
405 struct device_module_info i2c_elan_device_module = {
406 {
407 I2C_ELAN_DEVICE_NAME,
408 0,
409 NULL
410 },
411
412 i2c_elan_init_device,
413 i2c_elan_uninit_device,
414 NULL,
415
416 i2c_elan_open,
417 i2c_elan_close,
418 i2c_elan_free,
419 i2c_elan_read,
420 i2c_elan_write,
421 NULL,
422 i2c_elan_control,
423
424 NULL,
425 NULL
426 };
427
428
429 module_dependency module_dependencies[] = {
430 { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager },
431 {}
432 };
433
434
435 module_info *modules[] = {
436 (module_info *)&i2c_elan_driver_module,
437 (module_info *)&i2c_elan_device_module,
438 NULL
439 };
440