diff options
Diffstat (limited to 'device/hid/hid_service_linux.cc')
-rw-r--r-- | device/hid/hid_service_linux.cc | 161 |
1 files changed, 81 insertions, 80 deletions
diff --git a/device/hid/hid_service_linux.cc b/device/hid/hid_service_linux.cc index a1c6145..0cbf5cd 100644 --- a/device/hid/hid_service_linux.cc +++ b/device/hid/hid_service_linux.cc @@ -4,20 +4,18 @@ #include "device/hid/hid_service_linux.h" -#include <linux/hidraw.h> -#include <sys/ioctl.h> -#include <stdint.h> - #include <string> #include "base/bind.h" #include "base/files/file.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/logging.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" +#include "base/thread_task_runner_handle.h" #include "base/threading/thread_restrictions.h" #include "device/hid/hid_connection_linux.h" #include "device/hid/hid_device_info.h" @@ -38,6 +36,7 @@ const char kHidrawSubsystem[] = "hidraw"; const char kHIDID[] = "HID_ID"; const char kHIDName[] = "HID_NAME"; const char kHIDUnique[] = "HID_UNIQ"; +const char kSysfsReportDescriptorKey[] = "report_descriptor"; } // namespace @@ -46,12 +45,50 @@ HidServiceLinux::HidServiceLinux( : ui_task_runner_(ui_task_runner), weak_factory_(this) { base::ThreadRestrictions::AssertIOAllowed(); + task_runner_ = base::ThreadTaskRunnerHandle::Get(); DeviceMonitorLinux* monitor = DeviceMonitorLinux::GetInstance(); monitor->AddObserver(this); monitor->Enumerate( base::Bind(&HidServiceLinux::OnDeviceAdded, weak_factory_.GetWeakPtr())); } +#if defined(OS_CHROMEOS) +void HidServiceLinux::RequestAccess( + const HidDeviceId& device_id, + const base::Callback<void(bool success)>& callback) { + bool success = false; + ScopedUdevDevicePtr device = + DeviceMonitorLinux::GetInstance()->GetDeviceFromPath( + device_id); + + if (device) { + const char* dev_node = udev_device_get_devnode(device.get()); + + if (base::SysInfo::IsRunningOnChromeOS()) { + chromeos::PermissionBrokerClient* client = + chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); + DCHECK(client) << "Could not get permission broker client."; + if (client) { + ui_task_runner_->PostTask( + FROM_HERE, + base::Bind(&chromeos::PermissionBrokerClient::RequestPathAccess, + base::Unretained(client), + std::string(dev_node), + -1, + base::Bind(&HidServiceLinux::OnRequestAccessComplete, + weak_factory_.GetWeakPtr(), + callback))); + return; + } + } else { + // Not really running on Chrome OS, declare success. + success = true; + } + } + task_runner_->PostTask(FROM_HERE, base::Bind(callback, success)); +} +#endif + scoped_refptr<HidConnection> HidServiceLinux::Connect( const HidDeviceId& device_id) { HidDeviceInfo device_info; @@ -63,8 +100,10 @@ scoped_refptr<HidConnection> HidServiceLinux::Connect( device_info.device_id); if (device) { - std::string dev_node = udev_device_get_devnode(device.get()); - return new HidConnectionLinux(device_info, dev_node); + const char* dev_node = udev_device_get_devnode(device.get()); + if (dev_node) { + return new HidConnectionLinux(device_info, dev_node); + } } return NULL; @@ -86,8 +125,8 @@ void HidServiceLinux::OnDeviceAdded(udev_device* device) { if (!subsystem || strcmp(subsystem, kHidrawSubsystem) != 0) return; - scoped_ptr<HidDeviceInfo> device_info(new HidDeviceInfo); - device_info->device_id = device_path; + HidDeviceInfo device_info; + device_info.device_id = device_path; uint32_t int_property = 0; const char* str_property = NULL; @@ -98,8 +137,9 @@ void HidServiceLinux::OnDeviceAdded(udev_device* device) { } const char* hid_id = udev_device_get_property_value(parent, kHIDID); - if (!hid_id) + if (!hid_id) { return; + } std::vector<std::string> parts; base::SplitString(hid_id, ':', &parts); @@ -108,96 +148,57 @@ void HidServiceLinux::OnDeviceAdded(udev_device* device) { } if (HexStringToUInt(base::StringPiece(parts[1]), &int_property)) { - device_info->vendor_id = int_property; + device_info.vendor_id = int_property; } if (HexStringToUInt(base::StringPiece(parts[2]), &int_property)) { - device_info->product_id = int_property; + device_info.product_id = int_property; } str_property = udev_device_get_property_value(parent, kHIDUnique); - if (str_property != NULL) - device_info->serial_number = str_property; + if (str_property != NULL) { + device_info.serial_number = str_property; + } str_property = udev_device_get_property_value(parent, kHIDName); - if (str_property != NULL) - device_info->product_name = str_property; + if (str_property != NULL) { + device_info.product_name = str_property; + } - const std::string dev_node = udev_device_get_devnode(device); -#if defined(OS_CHROMEOS) - // ChromeOS builds on non-ChromeOS machines (dev) should not attempt to - // use permission broker. - if (base::SysInfo::IsRunningOnChromeOS()) { - chromeos::PermissionBrokerClient* client = - chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); - DCHECK(client) << "Could not get permission broker client."; - if (!client) { - return; - } - ui_task_runner_->PostTask( - FROM_HERE, - base::Bind(&chromeos::PermissionBrokerClient::RequestPathAccess, - base::Unretained(client), - dev_node, - -1, - base::Bind(&HidServiceLinux::OnRequestAccessComplete, - weak_factory_.GetWeakPtr(), - dev_node, - base::Passed(&device_info)))); - } else { - OnRequestAccessComplete(dev_node, device_info.Pass(), true); + const char* parent_sysfs_path = udev_device_get_syspath(parent); + if (!parent_sysfs_path) { + return; } -#else - OnRequestAccessComplete(dev_node, device_info.Pass(), true); -#endif // defined(OS_CHROMEOS) + base::FilePath report_descriptor_path = + base::FilePath(parent_sysfs_path).Append(kSysfsReportDescriptorKey); + std::string report_descriptor_str; + if (!base::ReadFileToString(report_descriptor_path, &report_descriptor_str)) { + return; + } + + HidReportDescriptor report_descriptor( + reinterpret_cast<uint8_t*>(&report_descriptor_str[0]), + report_descriptor_str.length()); + report_descriptor.GetDetails(&device_info.collections, + &device_info.has_report_id, + &device_info.max_input_report_size, + &device_info.max_output_report_size, + &device_info.max_feature_report_size); + + AddDevice(device_info); } void HidServiceLinux::OnDeviceRemoved(udev_device* device) { const char* device_path = udev_device_get_syspath(device);; - if (device_path) + if (device_path) { RemoveDevice(device_path); + } } void HidServiceLinux::OnRequestAccessComplete( - const std::string& path, - scoped_ptr<HidDeviceInfo> device_info, + const base::Callback<void(bool success)>& callback, bool success) { - const int flags = base::File::FLAG_OPEN | base::File::FLAG_READ; - base::File device_file(base::FilePath(path), flags); - if (!device_file.IsValid()) { - LOG(ERROR) << "Cannot open '" << path << "': " - << base::File::ErrorToString(device_file.error_details()); - return; - } - - int desc_size = 0; - int res = ioctl(device_file.GetPlatformFile(), HIDIOCGRDESCSIZE, &desc_size); - if (res < 0) { - PLOG(ERROR) << "Failed to get report descriptor size"; - device_file.Close(); - return; - } - - hidraw_report_descriptor rpt_desc; - rpt_desc.size = desc_size; - - res = ioctl(device_file.GetPlatformFile(), HIDIOCGRDESC, &rpt_desc); - if (res < 0) { - PLOG(ERROR) << "Failed to get report descriptor"; - device_file.Close(); - return; - } - - device_file.Close(); - - HidReportDescriptor report_descriptor(rpt_desc.value, rpt_desc.size); - report_descriptor.GetDetails(&device_info->collections, - &device_info->has_report_id, - &device_info->max_input_report_size, - &device_info->max_output_report_size, - &device_info->max_feature_report_size); - - AddDevice(*device_info); + task_runner_->PostTask(FROM_HERE, base::Bind(callback, success)); } } // namespace device |