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 107 i2c_elan_init_device(void *driverCookie, void **cookie) 108 { 109 *cookie = driverCookie; 110 return B_OK; 111 } 112 113 114 static void 115 i2c_elan_uninit_device(void *_cookie) 116 { 117 118 } 119 120 121 static status_t 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 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 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 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 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 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 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 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 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 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 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 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 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