xref: /haiku/src/add-ons/kernel/drivers/input/i2c_elan/Driver.cpp (revision e16045db2c5161f015ee8f92b26f15be126790df)
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