00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "OVR_Linux_HIDDevice.h"
00016
00017 #include <sys/ioctl.h>
00018 #include <fcntl.h>
00019 #include <errno.h>
00020 #include <linux/hidraw.h>
00021 #include "OVR_HIDDeviceImpl.h"
00022
00023 namespace OVR { namespace Linux {
00024
00025 static const UInt32 MAX_QUEUED_INPUT_REPORTS = 5;
00026
00027
00028
00029
00030 HIDDeviceManager::HIDDeviceManager(DeviceManager* manager) : DevManager(manager)
00031 {
00032 UdevInstance = NULL;
00033 HIDMonitor = NULL;
00034 HIDMonHandle = -1;
00035 }
00036
00037
00038 HIDDeviceManager::~HIDDeviceManager()
00039 {
00040 }
00041
00042
00043 bool HIDDeviceManager::initializeManager()
00044 {
00045 if (HIDMonitor)
00046 {
00047 return true;
00048 }
00049
00050
00051 HIDMonitor = udev_monitor_new_from_netlink(UdevInstance, "udev");
00052 if (HIDMonitor == NULL)
00053 {
00054 return false;
00055 }
00056
00057 udev_monitor_filter_add_match_subsystem_devtype(HIDMonitor, "hidraw", NULL);
00058
00059 int err = udev_monitor_enable_receiving(HIDMonitor);
00060 if (err)
00061 {
00062 udev_monitor_unref(HIDMonitor);
00063 HIDMonitor = NULL;
00064 return false;
00065 }
00066
00067
00068 HIDMonHandle = udev_monitor_get_fd(HIDMonitor);
00069 if (HIDMonHandle < 0)
00070 {
00071 udev_monitor_unref(HIDMonitor);
00072 HIDMonitor = NULL;
00073 return false;
00074 }
00075
00076
00077
00078 if (!DevManager->pThread->AddSelectFd(this, HIDMonHandle))
00079 {
00080 close(HIDMonHandle);
00081 HIDMonHandle = -1;
00082
00083 udev_monitor_unref(HIDMonitor);
00084 HIDMonitor = NULL;
00085 return false;
00086 }
00087
00088 return true;
00089 }
00090
00091
00092 bool HIDDeviceManager::Initialize()
00093 {
00094
00095
00096 UdevInstance = udev_new();
00097 if (!UdevInstance)
00098 return false;
00099
00100 return initializeManager();
00101 }
00102
00103
00104 void HIDDeviceManager::Shutdown()
00105 {
00106 OVR_ASSERT_LOG((UdevInstance), ("Should have called 'Initialize' before 'Shutdown'."));
00107
00108 if (HIDMonitor)
00109 {
00110 DevManager->pThread->RemoveSelectFd(this, HIDMonHandle);
00111 close(HIDMonHandle);
00112 HIDMonHandle = -1;
00113
00114 udev_monitor_unref(HIDMonitor);
00115 HIDMonitor = NULL;
00116 }
00117
00118 udev_unref(UdevInstance);
00119
00120 LogText("OVR::Linux::HIDDeviceManager - shutting down.\n");
00121 }
00122
00123
00124 bool HIDDeviceManager::AddNotificationDevice(HIDDevice* device)
00125 {
00126 NotificationDevices.PushBack(device);
00127 return true;
00128 }
00129
00130
00131 bool HIDDeviceManager::RemoveNotificationDevice(HIDDevice* device)
00132 {
00133 for (UPInt i = 0; i < NotificationDevices.GetSize(); i++)
00134 {
00135 if (NotificationDevices[i] == device)
00136 {
00137 NotificationDevices.RemoveAt(i);
00138 return true;
00139 }
00140 }
00141 return false;
00142 }
00143
00144
00145 bool HIDDeviceManager::getIntProperty(udev_device* device,
00146 const char* propertyName,
00147 SInt32* pResult)
00148 {
00149 const char* str = udev_device_get_sysattr_value(device, propertyName);
00150 if (str)
00151 {
00152 *pResult = strtol(str, NULL, 16);
00153 return true;
00154 }
00155 else
00156 {
00157 *pResult = 0;
00158 return true;
00159 }
00160 }
00161
00162
00163 bool HIDDeviceManager::initVendorProductVersion(udev_device* device, HIDDeviceDesc* pDevDesc)
00164 {
00165 SInt32 result;
00166 if (getIntProperty(device, "idVendor", &result))
00167 pDevDesc->VendorId = result;
00168 else
00169 return false;
00170
00171 if (getIntProperty(device, "idProduct", &result))
00172 pDevDesc->ProductId = result;
00173 else
00174 return false;
00175
00176 return true;
00177 }
00178
00179
00180 bool HIDDeviceManager::getStringProperty(udev_device* device,
00181 const char* propertyName,
00182 OVR::String* pResult)
00183 {
00184
00185 const char* str = udev_device_get_sysattr_value(device, propertyName);
00186 if (str)
00187 {
00188 *pResult = String(str);
00189 return true;
00190 }
00191 else
00192 {
00193 return false;
00194 }
00195 }
00196
00197
00198 bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor)
00199 {
00200
00201 if (!initializeManager())
00202 {
00203 return false;
00204 }
00205
00206
00207 udev_enumerate* devices = udev_enumerate_new(UdevInstance);
00208 udev_enumerate_add_match_subsystem(devices, "hidraw");
00209 udev_enumerate_scan_devices(devices);
00210
00211 udev_list_entry* entry = udev_enumerate_get_list_entry(devices);
00212
00213
00214 while (entry != NULL)
00215 {
00216
00217 const char* sysfs_path = udev_list_entry_get_name(entry);
00218 udev_device* hid;
00219 hid = udev_device_new_from_syspath(UdevInstance, sysfs_path);
00220 const char* dev_path = udev_device_get_devnode(hid);
00221
00222
00223 hid = udev_device_get_parent_with_subsystem_devtype(hid, "usb", "usb_device");
00224 if (hid)
00225 {
00226 HIDDeviceDesc devDesc;
00227
00228
00229 if (dev_path &&
00230 initVendorProductVersion(hid, &devDesc) &&
00231 enumVisitor->MatchVendorProduct(devDesc.VendorId, devDesc.ProductId))
00232 {
00233 devDesc.Path = dev_path;
00234 getFullDesc(hid, &devDesc);
00235
00236
00237 Ptr<DeviceCreateDesc> existingDevice = DevManager->FindHIDDevice(devDesc);
00238
00239
00240 if (existingDevice && existingDevice->pDevice)
00241 {
00242 existingDevice->Enumerated = true;
00243 }
00244 else
00245 {
00246 int device_handle = open(dev_path, O_RDWR);
00247 if (device_handle >= 0)
00248 {
00249
00250 Linux::HIDDevice device(this, device_handle);
00251 enumVisitor->Visit(device, devDesc);
00252
00253 close(device_handle);
00254 }
00255 }
00256 }
00257
00258 udev_device_unref(hid);
00259 entry = udev_list_entry_get_next(entry);
00260 }
00261 }
00262
00263
00264 udev_enumerate_unref(devices);
00265
00266 return true;
00267 }
00268
00269
00270 OVR::HIDDevice* HIDDeviceManager::Open(const String& path)
00271 {
00272 Ptr<Linux::HIDDevice> device = *new Linux::HIDDevice(this);
00273
00274 if (device->HIDInitialize(path))
00275 {
00276 device->AddRef();
00277 return device;
00278 }
00279
00280 return NULL;
00281 }
00282
00283
00284 bool HIDDeviceManager::getFullDesc(udev_device* device, HIDDeviceDesc* desc)
00285 {
00286
00287 if (!initVendorProductVersion(device, desc))
00288 {
00289 return false;
00290 }
00291
00292 if (!getStringProperty(device, "serial", &(desc->SerialNumber)))
00293 {
00294 return false;
00295 }
00296
00297 getStringProperty(device, "manufacturer", &(desc->Manufacturer));
00298 getStringProperty(device, "product", &(desc->Product));
00299
00300 return true;
00301 }
00302
00303
00304 bool HIDDeviceManager::GetDescriptorFromPath(const char* dev_path, HIDDeviceDesc* desc)
00305 {
00306 if (!initializeManager())
00307 {
00308 return false;
00309 }
00310
00311
00312
00313
00314 udev_enumerate* devices = udev_enumerate_new(UdevInstance);
00315 udev_enumerate_add_match_subsystem(devices, "hidraw");
00316 udev_enumerate_scan_devices(devices);
00317
00318 udev_list_entry* entry = udev_enumerate_get_list_entry(devices);
00319
00320 bool success = false;
00321
00322 while (entry != NULL)
00323 {
00324
00325 const char* sysfs_path = udev_list_entry_get_name(entry);
00326 udev_device* hid;
00327 hid = udev_device_new_from_syspath(UdevInstance, sysfs_path);
00328 const char* path = udev_device_get_devnode(hid);
00329
00330 if (OVR_strcmp(dev_path, path) == 0)
00331 {
00332
00333
00334 hid = udev_device_get_parent_with_subsystem_devtype(hid, "usb", "usb_device");
00335 if (hid)
00336 {
00337 desc->Path = dev_path;
00338 success = getFullDesc(hid, desc);
00339 }
00340
00341 }
00342
00343 udev_device_unref(hid);
00344 entry = udev_list_entry_get_next(entry);
00345 }
00346
00347
00348 udev_enumerate_unref(devices);
00349
00350 return success;
00351 }
00352
00353
00354 void HIDDeviceManager::OnEvent(int i, int fd)
00355 {
00356
00357 udev_device* hid = udev_monitor_receive_device(HIDMonitor);
00358 if (hid)
00359 {
00360 const char* dev_path = udev_device_get_devnode(hid);
00361 const char* action = udev_device_get_action(hid);
00362
00363 HIDDeviceDesc device_info;
00364 device_info.Path = dev_path;
00365
00366 MessageType notify_type;
00367 if (OVR_strcmp(action, "add") == 0)
00368 {
00369 notify_type = Message_DeviceAdded;
00370
00371
00372
00373
00374
00375 hid = udev_device_get_parent_with_subsystem_devtype(hid, "usb", "usb_device");
00376 if (!hid)
00377 {
00378 return;
00379 }
00380
00381 getFullDesc(hid, &device_info);
00382 }
00383 else if (OVR_strcmp(action, "remove") == 0)
00384 {
00385 notify_type = Message_DeviceRemoved;
00386 }
00387 else
00388 {
00389 return;
00390 }
00391
00392 bool error = false;
00393 bool deviceFound = false;
00394 for (UPInt i = 0; i < NotificationDevices.GetSize(); i++)
00395 {
00396 if (NotificationDevices[i] &&
00397 NotificationDevices[i]->OnDeviceNotification(notify_type, &device_info, &error))
00398 {
00399
00400 deviceFound = true;
00401 break;
00402 }
00403 }
00404
00405 if (notify_type == Message_DeviceAdded && !deviceFound)
00406 {
00407 DevManager->DetectHIDDevice(device_info);
00408 }
00409
00410 udev_device_unref(hid);
00411 }
00412 }
00413
00414
00415
00416
00417 HIDDevice::HIDDevice(HIDDeviceManager* manager)
00418 : HIDManager(manager), InMinimalMode(false)
00419 {
00420 DeviceHandle = -1;
00421 }
00422
00423
00424
00425
00426 HIDDevice::HIDDevice(HIDDeviceManager* manager, int device_handle)
00427 : HIDManager(manager), DeviceHandle(device_handle), InMinimalMode(true)
00428 {
00429 }
00430
00431
00432 HIDDevice::~HIDDevice()
00433 {
00434 if (!InMinimalMode)
00435 {
00436 HIDShutdown();
00437 }
00438 }
00439
00440
00441 bool HIDDevice::HIDInitialize(const String& path)
00442 {
00443 const char* hid_path = path.ToCStr();
00444 if (!openDevice(hid_path))
00445 {
00446 LogText("OVR::Linux::HIDDevice - Failed to open HIDDevice: %s", hid_path);
00447 return false;
00448 }
00449
00450 HIDManager->DevManager->pThread->AddTicksNotifier(this);
00451 HIDManager->AddNotificationDevice(this);
00452
00453 LogText("OVR::Linux::HIDDevice - Opened '%s'\n"
00454 " Manufacturer:'%s' Product:'%s' Serial#:'%s'\n",
00455 DevDesc.Path.ToCStr(),
00456 DevDesc.Manufacturer.ToCStr(), DevDesc.Product.ToCStr(),
00457 DevDesc.SerialNumber.ToCStr());
00458
00459 return true;
00460 }
00461
00462
00463 bool HIDDevice::initInfo()
00464 {
00465
00466 OVR_ASSERT(DeviceHandle >= 0);
00467
00468 int desc_size = 0;
00469 hidraw_report_descriptor rpt_desc;
00470 memset(&rpt_desc, 0, sizeof(rpt_desc));
00471
00472
00473 int r = ioctl(DeviceHandle, HIDIOCGRDESCSIZE, &desc_size);
00474 if (r < 0)
00475 {
00476 OVR_ASSERT_LOG(false, ("Failed to get report descriptor size."));
00477 return false;
00478 }
00479
00480
00481 rpt_desc.size = desc_size;
00482 r = ioctl(DeviceHandle, HIDIOCGRDESC, &rpt_desc);
00483 if (r < 0)
00484 {
00485 OVR_ASSERT_LOG(false, ("Failed to get report descriptor."));
00486 return false;
00487 }
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 InputReportBufferLength = 62;
00524 OutputReportBufferLength = 0;
00525 FeatureReportBufferLength = 69;
00526
00527 if (ReadBufferSize < InputReportBufferLength)
00528 {
00529 OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer."));
00530 return false;
00531 }
00532
00533 return true;
00534 }
00535
00536
00537 bool HIDDevice::openDevice(const char* device_path)
00538 {
00539
00540 if (!HIDManager->GetDescriptorFromPath(device_path, &DevDesc))
00541 {
00542 return false;
00543 }
00544
00545
00546 DeviceHandle = open(device_path, O_RDWR);
00547 if (DeviceHandle < 0)
00548 {
00549 OVR_DEBUG_LOG(("Failed 'CreateHIDFile' while opening device, error = 0x%X.", errno));
00550 DeviceHandle = -1;
00551 return false;
00552 }
00553
00554
00555 if (!initInfo())
00556 {
00557 OVR_ASSERT_LOG(false, ("Failed to get HIDDevice info."));
00558
00559 close(DeviceHandle);
00560 DeviceHandle = -1;
00561 return false;
00562 }
00563
00564
00565 if (!HIDManager->DevManager->pThread->AddSelectFd(this, DeviceHandle))
00566 {
00567 OVR_ASSERT_LOG(false, ("Failed to initialize polling for HIDDevice."));
00568
00569 close(DeviceHandle);
00570 DeviceHandle = -1;
00571 return false;
00572 }
00573
00574 return true;
00575 }
00576
00577
00578 void HIDDevice::HIDShutdown()
00579 {
00580
00581 HIDManager->DevManager->pThread->RemoveTicksNotifier(this);
00582 HIDManager->RemoveNotificationDevice(this);
00583
00584 if (DeviceHandle >= 0)
00585 {
00586 closeDevice(false);
00587 }
00588
00589 LogText("OVR::Linux::HIDDevice - HIDShutdown '%s'\n", DevDesc.Path.ToCStr());
00590 }
00591
00592
00593 void HIDDevice::closeDevice(bool wasUnplugged)
00594 {
00595 OVR_ASSERT(DeviceHandle >= 0);
00596
00597
00598 HIDManager->DevManager->pThread->RemoveSelectFd(this, DeviceHandle);
00599
00600 close(DeviceHandle);
00601 DeviceHandle = -1;
00602
00603 LogText("OVR::Linux::HIDDevice - HID Device Closed '%s'\n", DevDesc.Path.ToCStr());
00604 }
00605
00606
00607 void HIDDevice::closeDeviceOnIOError()
00608 {
00609 LogText("OVR::Linux::HIDDevice - Lost connection to '%s'\n", DevDesc.Path.ToCStr());
00610 closeDevice(false);
00611 }
00612
00613
00614 bool HIDDevice::SetFeatureReport(UByte* data, UInt32 length)
00615 {
00616
00617 if (DeviceHandle < 0)
00618 return false;
00619
00620 UByte reportID = data[0];
00621
00622 if (reportID == 0)
00623 {
00624
00625 data++;
00626 length--;
00627 }
00628
00629 int r = ioctl(DeviceHandle, HIDIOCSFEATURE(length), data);
00630 return (r >= 0);
00631 }
00632
00633
00634 bool HIDDevice::GetFeatureReport(UByte* data, UInt32 length)
00635 {
00636 if (DeviceHandle < 0)
00637 return false;
00638
00639 int r = ioctl(DeviceHandle, HIDIOCGFEATURE(length), data);
00640 return (r >= 0);
00641 }
00642
00643
00644 UInt64 HIDDevice::OnTicks(UInt64 ticksMks)
00645 {
00646 if (Handler)
00647 {
00648 return Handler->OnTicks(ticksMks);
00649 }
00650
00651 return DeviceManagerThread::Notifier::OnTicks(ticksMks);
00652 }
00653
00654
00655 void HIDDevice::OnEvent(int i, int fd)
00656 {
00657
00658 int bytes = read(fd, ReadBuffer, ReadBufferSize);
00659 if (bytes >= 0)
00660 {
00661
00662 if (Handler)
00663 {
00664 Handler->OnInputReport(ReadBuffer, bytes);
00665 }
00666 }
00667 else
00668 {
00669 closeDeviceOnIOError();
00670 }
00671 }
00672
00673
00674 bool HIDDevice::OnDeviceNotification(MessageType messageType,
00675 HIDDeviceDesc* device_info,
00676 bool* error)
00677 {
00678 const char* device_path = device_info->Path.ToCStr();
00679
00680 if (messageType == Message_DeviceAdded && DeviceHandle < 0)
00681 {
00682
00683 if (!(device_info->VendorId == DevDesc.VendorId
00684 && device_info->ProductId == DevDesc.ProductId
00685 && device_info->SerialNumber == DevDesc.SerialNumber))
00686 {
00687 return false;
00688 }
00689
00690
00691 if (!openDevice(device_path))
00692 {
00693 LogError("OVR::Linux::HIDDevice - Failed to reopen a device '%s' that was re-added.\n",
00694 device_path);
00695 *error = true;
00696 return true;
00697 }
00698
00699 LogText("OVR::Linux::HIDDevice - Reopened device '%s'\n", device_path);
00700
00701 if (Handler)
00702 {
00703 Handler->OnDeviceMessage(HIDHandler::HIDDeviceMessage_DeviceAdded);
00704 }
00705 }
00706 else if (messageType == Message_DeviceRemoved)
00707 {
00708
00709
00710
00711 if (DevDesc.Path.CompareNoCase(device_path) != 0)
00712 {
00713 return false;
00714 }
00715
00716 if (DeviceHandle >= 0)
00717 {
00718 closeDevice(true);
00719 }
00720
00721 if (Handler)
00722 {
00723 Handler->OnDeviceMessage(HIDHandler::HIDDeviceMessage_DeviceRemoved);
00724 }
00725 }
00726 else
00727 {
00728 OVR_ASSERT(0);
00729 }
00730
00731 *error = false;
00732 return true;
00733 }
00734
00735
00736 HIDDeviceManager* HIDDeviceManager::CreateInternal(Linux::DeviceManager* devManager)
00737 {
00738
00739 if (!System::IsInitialized())
00740 {
00741
00742 OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
00743 LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
00744 return 0;
00745 }
00746
00747 Ptr<Linux::HIDDeviceManager> manager = *new Linux::HIDDeviceManager(devManager);
00748
00749 if (manager)
00750 {
00751 if (manager->Initialize())
00752 {
00753 manager->AddRef();
00754 }
00755 else
00756 {
00757 manager.Clear();
00758 }
00759 }
00760
00761 return manager.GetPtr();
00762 }
00763
00764 }
00765
00766
00767
00768
00769
00770 HIDDeviceManager* HIDDeviceManager::Create()
00771 {
00772 OVR_ASSERT_LOG(false, ("Standalone mode not implemented yet."));
00773
00774 if (!System::IsInitialized())
00775 {
00776
00777 OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
00778 LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
00779 return 0;
00780 }
00781
00782 Ptr<Linux::HIDDeviceManager> manager = *new Linux::HIDDeviceManager(NULL);
00783
00784 if (manager)
00785 {
00786 if (manager->Initialize())
00787 {
00788 manager->AddRef();
00789 }
00790 else
00791 {
00792 manager.Clear();
00793 }
00794 }
00795
00796 return manager.GetPtr();
00797 }
00798
00799 }