1 /* 2 * Copyright 2020, Jérôme Duval, jerome.duval@gmail.com. 3 * Copyright 2008-2011 Michael Lotz <mmlr@mlotz.ch> 4 * Distributed under the terms of the MIT license. 5 */ 6 7 8 //! Driver for I2C Human Interface Devices. 9 10 11 #include <ACPI.h> 12 #include <device_manager.h> 13 #include <i2c.h> 14 15 #include "DeviceList.h" 16 #include "Driver.h" 17 #include "HIDDevice.h" 18 #include "ProtocolHandler.h" 19 20 #include <lock.h> 21 #include <util/AutoLock.h> 22 23 #include <new> 24 #include <stdio.h> 25 #include <string.h> 26 27 28 29 struct hid_driver_cookie { 30 device_node* node; 31 i2c_device_interface* i2c; 32 i2c_device i2c_cookie; 33 uint32 descriptorAddress; 34 HIDDevice* hidDevice; 35 }; 36 37 struct device_cookie { 38 ProtocolHandler* handler; 39 uint32 cookie; 40 hid_driver_cookie* driver_cookie; 41 }; 42 43 44 #define I2C_HID_DRIVER_NAME "drivers/input/i2c_hid/driver_v1" 45 #define I2C_HID_DEVICE_NAME "drivers/input/i2c_hid/device_v1" 46 47 /* Base Namespace devices are published to */ 48 #define I2C_HID_BASENAME "input/i2c_hid/%d" 49 50 // name of pnp generator of path ids 51 #define I2C_HID_PATHID_GENERATOR "i2c_hid/path_id" 52 53 #define ACPI_NAME_HID_DEVICE "PNP0C50" 54 55 static device_manager_info *sDeviceManager; 56 static acpi_module_info* gACPI; 57 58 DeviceList *gDeviceList = NULL; 59 static mutex sDriverLock; 60 61 62 static acpi_object_type* 63 acpi_evaluate_dsm(acpi_handle handle, const uint8 *guid, uint64 revision, uint64 function) 64 { 65 acpi_data buffer; 66 buffer.pointer = NULL; 67 buffer.length = ACPI_ALLOCATE_BUFFER; 68 69 acpi_object_type array[4]; 70 acpi_objects acpi_objects; 71 acpi_objects.count = 4; 72 acpi_objects.pointer = array; 73 74 array[0].object_type = ACPI_TYPE_BUFFER; 75 array[0].buffer.buffer = (void*)guid; 76 array[0].buffer.length = 16; 77 78 array[1].object_type = ACPI_TYPE_INTEGER; 79 array[1].integer.integer = revision; 80 81 array[2].object_type = ACPI_TYPE_INTEGER; 82 array[2].integer.integer = function; 83 84 array[3].object_type = ACPI_TYPE_PACKAGE; 85 array[3].package.objects = NULL; 86 array[3].package.count = 0; 87 88 if (gACPI->evaluate_method(handle, "_DSM", &acpi_objects, &buffer) == B_OK) 89 return (acpi_object_type*)buffer.pointer; 90 return NULL; 91 } 92 93 94 // #pragma mark - notify hooks 95 96 97 /* 98 status_t 99 i2c_hid_device_removed(void *cookie) 100 { 101 mutex_lock(&sDriverLock); 102 int32 parentCookie = (int32)(addr_t)cookie; 103 TRACE("device_removed(%" B_PRId32 ")\n", parentCookie); 104 105 for (int32 i = 0; i < gDeviceList->CountDevices(); i++) { 106 ProtocolHandler *handler = (ProtocolHandler *)gDeviceList->DeviceAt(i); 107 if (!handler) 108 continue; 109 110 HIDDevice *device = handler->Device(); 111 if (device->ParentCookie() != parentCookie) 112 continue; 113 114 // remove all the handlers 115 for (uint32 i = 0;; i++) { 116 handler = device->ProtocolHandlerAt(i); 117 if (handler == NULL) 118 break; 119 120 gDeviceList->RemoveDevice(NULL, handler); 121 } 122 123 // this handler's device belongs to the one removed 124 if (device->IsOpen()) { 125 // the device and it's handlers will be deleted in the free hook 126 device->Removed(); 127 } else 128 delete device; 129 130 break; 131 } 132 133 mutex_unlock(&sDriverLock); 134 return B_OK; 135 }*/ 136 137 138 // #pragma mark - driver hooks 139 140 141 static status_t 142 i2c_hid_init_device(void *driverCookie, void **cookie) 143 { 144 *cookie = driverCookie; 145 return B_OK; 146 } 147 148 149 static void 150 i2c_hid_uninit_device(void *_cookie) 151 { 152 153 } 154 155 156 static status_t 157 i2c_hid_open(void *initCookie, const char *path, int flags, void **_cookie) 158 { 159 TRACE("open(%s, %" B_PRIu32 ", %p)\n", path, flags, _cookie); 160 161 device_cookie *cookie = new(std::nothrow) device_cookie(); 162 if (cookie == NULL) 163 return B_NO_MEMORY; 164 cookie->driver_cookie = (hid_driver_cookie*)initCookie; 165 166 MutexLocker locker(sDriverLock); 167 168 ProtocolHandler *handler = (ProtocolHandler *)gDeviceList->FindDevice(path); 169 TRACE(" path %s: handler %p\n", path, handler); 170 171 cookie->handler = handler; 172 cookie->cookie = 0; 173 174 status_t result = handler == NULL ? B_ENTRY_NOT_FOUND : B_OK; 175 if (result == B_OK) 176 result = handler->Open(flags, &cookie->cookie); 177 178 if (result != B_OK) { 179 delete cookie; 180 return result; 181 } 182 183 *_cookie = cookie; 184 185 return B_OK; 186 } 187 188 189 static status_t 190 i2c_hid_read(void *_cookie, off_t position, void *buffer, size_t *numBytes) 191 { 192 device_cookie *cookie = (device_cookie *)_cookie; 193 194 TRACE("read(%p, %" B_PRIu64 ", %p, %p (%" B_PRIuSIZE ")\n", cookie, position, buffer, numBytes, 195 numBytes != NULL ? *numBytes : 0); 196 return cookie->handler->Read(&cookie->cookie, position, buffer, numBytes); 197 } 198 199 200 static status_t 201 i2c_hid_write(void *_cookie, off_t position, const void *buffer, 202 size_t *numBytes) 203 { 204 device_cookie *cookie = (device_cookie *)_cookie; 205 206 TRACE("write(%p, %" B_PRIu64 ", %p, %p (%" B_PRIuSIZE ")\n", cookie, position, buffer, numBytes, 207 numBytes != NULL ? *numBytes : 0); 208 return cookie->handler->Write(&cookie->cookie, position, buffer, numBytes); 209 } 210 211 212 static status_t 213 i2c_hid_control(void *_cookie, uint32 op, void *buffer, size_t length) 214 { 215 device_cookie *cookie = (device_cookie *)_cookie; 216 217 TRACE("control(%p, %" B_PRIu32 ", %p, %" B_PRIuSIZE ")\n", cookie, op, buffer, length); 218 return cookie->handler->Control(&cookie->cookie, op, buffer, length); 219 } 220 221 222 static status_t 223 i2c_hid_close(void *_cookie) 224 { 225 device_cookie *cookie = (device_cookie *)_cookie; 226 227 TRACE("close(%p)\n", cookie); 228 return cookie->handler->Close(&cookie->cookie); 229 } 230 231 232 static status_t 233 i2c_hid_free(void *_cookie) 234 { 235 device_cookie *cookie = (device_cookie *)_cookie; 236 TRACE("free(%p)\n", cookie); 237 238 mutex_lock(&sDriverLock); 239 240 HIDDevice *device = cookie->handler->Device(); 241 if (device->IsOpen()) { 242 // another handler of this device is still open so we can't free it 243 } else if (device->IsRemoved()) { 244 // the parent device is removed already and none of its handlers are 245 // open anymore so we can free it here 246 delete device; 247 } 248 249 mutex_unlock(&sDriverLock); 250 251 delete cookie; 252 return B_OK; 253 } 254 255 256 // #pragma mark - driver module API 257 258 259 static float 260 i2c_hid_support(device_node *parent) 261 { 262 CALLED(); 263 264 // make sure parent is really the I2C bus manager 265 const char *bus; 266 if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) 267 return -1; 268 269 if (strcmp(bus, "i2c")) 270 return 0.0; 271 TRACE("i2c_hid_support found an i2c device %p\n", parent); 272 273 // check whether it's an HID device 274 uint64 handlePointer; 275 if (sDeviceManager->get_attr_uint64(parent, ACPI_DEVICE_HANDLE_ITEM, 276 &handlePointer, false) != B_OK) { 277 TRACE("i2c_hid_support found an i2c device without acpi handle\n"); 278 return B_ERROR; 279 } 280 281 const char *name; 282 if (sDeviceManager->get_attr_string(parent, ACPI_DEVICE_HID_ITEM, &name, 283 false) == B_OK && strcmp(name, ACPI_NAME_HID_DEVICE) == 0) { 284 TRACE("i2c_hid_support found an hid i2c device\n"); 285 return 0.6; 286 } 287 288 if (sDeviceManager->get_attr_string(parent, ACPI_DEVICE_CID_ITEM, &name, 289 false) == B_OK && strcmp(name, ACPI_NAME_HID_DEVICE) == 0) { 290 TRACE("i2c_hid_support found a compatible hid i2c device\n"); 291 return 0.6; 292 } 293 294 uint16 slaveAddress; 295 if (sDeviceManager->get_attr_uint16(parent, I2C_DEVICE_SLAVE_ADDR_ITEM, 296 &slaveAddress, false) != B_OK) { 297 TRACE("i2c_hid_support found a non hid without addr i2c device\n"); 298 return B_ERROR; 299 } 300 301 TRACE("i2c_hid_support found a non hid i2c device\n"); 302 303 return 0.0; 304 } 305 306 307 static status_t 308 i2c_hid_register_device(device_node *node) 309 { 310 CALLED(); 311 312 acpi_handle handle; 313 if (sDeviceManager->get_attr_uint64(node, ACPI_DEVICE_HANDLE_ITEM, 314 (uint64*)&handle, false) != B_OK) { 315 return B_DEVICE_NOT_FOUND; 316 } 317 318 static uint8_t acpiHidGuid[] = { 0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 319 0x45, 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE }; 320 acpi_object_type* object = acpi_evaluate_dsm(handle, acpiHidGuid, 1, 1); 321 if (object == NULL) 322 return B_DEVICE_NOT_FOUND; 323 if (object->object_type != ACPI_TYPE_INTEGER) { 324 free(object); 325 return B_DEVICE_NOT_FOUND; 326 } 327 328 uint32 descriptorAddress = object->integer.integer; 329 free(object); 330 device_attr attrs[] = { 331 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = "I2C HID Device" }}, 332 { "descriptorAddress", B_UINT32_TYPE, { .ui32 = descriptorAddress }}, 333 { NULL } 334 }; 335 336 return sDeviceManager->register_node(node, I2C_HID_DRIVER_NAME, attrs, 337 NULL, NULL); 338 } 339 340 341 static status_t 342 i2c_hid_init_driver(device_node *node, void **driverCookie) 343 { 344 CALLED(); 345 346 uint32 descriptorAddress; 347 if (sDeviceManager->get_attr_uint32(node, "descriptorAddress", 348 &descriptorAddress, false) != B_OK) { 349 return B_DEVICE_NOT_FOUND; 350 } 351 352 hid_driver_cookie *device 353 = (hid_driver_cookie *)calloc(1, sizeof(hid_driver_cookie)); 354 if (device == NULL) 355 return B_NO_MEMORY; 356 357 *driverCookie = device; 358 359 device->node = node; 360 device->descriptorAddress = descriptorAddress; 361 362 device_node *parent; 363 parent = sDeviceManager->get_parent_node(node); 364 sDeviceManager->get_driver(parent, (driver_module_info **)&device->i2c, 365 (void **)&device->i2c_cookie); 366 sDeviceManager->put_node(parent); 367 368 mutex_lock(&sDriverLock); 369 HIDDevice *hidDevice 370 = new(std::nothrow) HIDDevice(descriptorAddress, device->i2c, 371 device->i2c_cookie); 372 373 if (hidDevice != NULL && hidDevice->InitCheck() == B_OK) { 374 device->hidDevice = hidDevice; 375 } else 376 delete hidDevice; 377 378 mutex_unlock(&sDriverLock); 379 380 return device->hidDevice != NULL ? B_OK : B_IO_ERROR; 381 } 382 383 384 static void 385 i2c_hid_uninit_driver(void *driverCookie) 386 { 387 CALLED(); 388 hid_driver_cookie *device = (hid_driver_cookie*)driverCookie; 389 390 free(device); 391 } 392 393 394 static status_t 395 i2c_hid_register_child_devices(void *cookie) 396 { 397 CALLED(); 398 hid_driver_cookie *device = (hid_driver_cookie*)cookie; 399 HIDDevice* hidDevice = device->hidDevice; 400 if (hidDevice == NULL) 401 return B_OK; 402 for (uint32 i = 0;; i++) { 403 ProtocolHandler *handler = hidDevice->ProtocolHandlerAt(i); 404 if (handler == NULL) 405 break; 406 407 // As devices can be un- and replugged at will, we cannot 408 // simply rely on a device count. If there is just one 409 // keyboard, this does not mean that it uses the 0 name. 410 // There might have been two keyboards and the one using 0 411 // might have been unplugged. So we just generate names 412 // until we find one that is not currently in use. 413 int32 index = 0; 414 char pathBuffer[128]; 415 const char *basePath = handler->BasePath(); 416 while (true) { 417 sprintf(pathBuffer, "%s%" B_PRId32, basePath, index++); 418 if (gDeviceList->FindDevice(pathBuffer) == NULL) { 419 // this name is still free, use it 420 handler->SetPublishPath(strdup(pathBuffer)); 421 break; 422 } 423 } 424 425 gDeviceList->AddDevice(handler->PublishPath(), handler); 426 427 sDeviceManager->publish_device(device->node, pathBuffer, 428 I2C_HID_DEVICE_NAME); 429 } 430 431 432 /* int pathID = sDeviceManager->create_id(I2C_HID_PATHID_GENERATOR); 433 if (pathID < 0) { 434 ERROR("register_child_devices: couldn't create a path_id\n"); 435 return B_ERROR; 436 }*/ 437 return B_OK; 438 } 439 440 441 static status_t 442 std_ops(int32 op, ...) 443 { 444 switch (op) { 445 case B_MODULE_INIT: 446 gDeviceList = new(std::nothrow) DeviceList(); 447 if (gDeviceList == NULL) { 448 return B_NO_MEMORY; 449 } 450 mutex_init(&sDriverLock, "i2c hid driver lock"); 451 452 return B_OK; 453 case B_MODULE_UNINIT: 454 delete gDeviceList; 455 gDeviceList = NULL; 456 mutex_destroy(&sDriverLock); 457 return B_OK; 458 459 default: 460 break; 461 } 462 463 return B_ERROR; 464 } 465 466 467 // #pragma mark - 468 469 470 driver_module_info i2c_hid_driver_module = { 471 { 472 I2C_HID_DRIVER_NAME, 473 0, 474 &std_ops 475 }, 476 477 i2c_hid_support, 478 i2c_hid_register_device, 479 i2c_hid_init_driver, 480 i2c_hid_uninit_driver, 481 i2c_hid_register_child_devices, 482 NULL, // rescan 483 NULL, // removed 484 }; 485 486 487 struct device_module_info i2c_hid_device_module = { 488 { 489 I2C_HID_DEVICE_NAME, 490 0, 491 NULL 492 }, 493 494 i2c_hid_init_device, 495 i2c_hid_uninit_device, 496 NULL, 497 498 i2c_hid_open, 499 i2c_hid_close, 500 i2c_hid_free, 501 i2c_hid_read, 502 i2c_hid_write, 503 NULL, 504 i2c_hid_control, 505 506 NULL, 507 NULL 508 }; 509 510 511 module_dependency module_dependencies[] = { 512 { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager }, 513 { B_ACPI_MODULE_NAME, (module_info**)&gACPI }, 514 {} 515 }; 516 517 518 module_info *modules[] = { 519 (module_info *)&i2c_hid_driver_module, 520 (module_info *)&i2c_hid_device_module, 521 NULL 522 }; 523