OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "device/hid/hid_service_linux.h" | 5 #include "device/hid/hid_service_linux.h" |
6 | 6 |
7 #include <linux/hidraw.h> | 7 #include <linux/hidraw.h> |
8 #include <sys/ioctl.h> | 8 #include <sys/ioctl.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
11 #include <string> | 11 #include <string> |
12 | 12 |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/files/file.h" | 14 #include "base/files/file.h" |
15 #include "base/files/file_path.h" | 15 #include "base/files/file_path.h" |
16 #include "base/logging.h" | 16 #include "base/logging.h" |
17 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
18 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
19 #include "base/strings/string_piece.h" | 19 #include "base/strings/string_piece.h" |
20 #include "base/strings/string_split.h" | 20 #include "base/strings/string_split.h" |
21 #include "device/hid/hid_connection_linux.h" | 21 #include "device/hid/hid_connection_linux.h" |
22 #include "device/hid/hid_device_info.h" | 22 #include "device/hid/hid_device_info.h" |
23 #include "device/hid/hid_report_descriptor.h" | 23 #include "device/hid/hid_report_descriptor.h" |
24 #include "device/udev_linux/udev.h" | 24 #include "device/udev_linux/udev.h" |
25 | 25 |
| 26 #if defined(OS_CHROMEOS) |
| 27 #include "base/sys_info.h" |
| 28 #include "chromeos/dbus/dbus_thread_manager.h" |
| 29 #include "chromeos/dbus/permission_broker_client.h" |
| 30 #endif // defined(OS_CHROMEOS) |
| 31 |
26 namespace device { | 32 namespace device { |
27 | 33 |
28 namespace { | 34 namespace { |
29 | 35 |
30 const char kHidrawSubsystem[] = "hidraw"; | 36 const char kHidrawSubsystem[] = "hidraw"; |
31 const char kHIDID[] = "HID_ID"; | 37 const char kHIDID[] = "HID_ID"; |
32 const char kHIDName[] = "HID_NAME"; | 38 const char kHIDName[] = "HID_NAME"; |
33 const char kHIDUnique[] = "HID_UNIQ"; | 39 const char kHIDUnique[] = "HID_UNIQ"; |
34 | 40 |
35 } // namespace | 41 } // namespace |
36 | 42 |
37 HidServiceLinux::HidServiceLinux() { | 43 HidServiceLinux::HidServiceLinux( |
| 44 scoped_refptr<base::MessageLoopProxy> ui_message_loop) |
| 45 : ui_message_loop_(ui_message_loop), |
| 46 weak_factory_(this) { |
38 DeviceMonitorLinux* monitor = DeviceMonitorLinux::GetInstance(); | 47 DeviceMonitorLinux* monitor = DeviceMonitorLinux::GetInstance(); |
39 monitor->AddObserver(this); | 48 monitor->AddObserver(this); |
40 monitor->Enumerate( | 49 monitor->Enumerate( |
41 base::Bind(&HidServiceLinux::OnDeviceAdded, base::Unretained(this))); | 50 base::Bind(&HidServiceLinux::OnDeviceAdded, weak_factory_.GetWeakPtr())); |
42 } | 51 } |
43 | 52 |
44 scoped_refptr<HidConnection> HidServiceLinux::Connect( | 53 scoped_refptr<HidConnection> HidServiceLinux::Connect( |
45 const HidDeviceId& device_id) { | 54 const HidDeviceId& device_id) { |
46 HidDeviceInfo device_info; | 55 HidDeviceInfo device_info; |
47 if (!GetDeviceInfo(device_id, &device_info)) | 56 if (!GetDeviceInfo(device_id, &device_info)) |
48 return NULL; | 57 return NULL; |
49 | 58 |
50 ScopedUdevDevicePtr device = | 59 ScopedUdevDevicePtr device = |
51 DeviceMonitorLinux::GetInstance()->GetDeviceFromPath( | 60 DeviceMonitorLinux::GetInstance()->GetDeviceFromPath( |
(...skipping 16 matching lines...) Expand all Loading... |
68 if (!device) | 77 if (!device) |
69 return; | 78 return; |
70 | 79 |
71 const char* device_path = udev_device_get_syspath(device); | 80 const char* device_path = udev_device_get_syspath(device); |
72 if (!device_path) | 81 if (!device_path) |
73 return; | 82 return; |
74 const char* subsystem = udev_device_get_subsystem(device); | 83 const char* subsystem = udev_device_get_subsystem(device); |
75 if (!subsystem || strcmp(subsystem, kHidrawSubsystem) != 0) | 84 if (!subsystem || strcmp(subsystem, kHidrawSubsystem) != 0) |
76 return; | 85 return; |
77 | 86 |
78 HidDeviceInfo device_info; | 87 scoped_ptr<HidDeviceInfo> device_info(new HidDeviceInfo); |
79 device_info.device_id = device_path; | 88 device_info->device_id = device_path; |
80 | 89 |
81 uint32_t int_property = 0; | 90 uint32_t int_property = 0; |
82 const char* str_property = NULL; | 91 const char* str_property = NULL; |
83 | 92 |
84 udev_device *parent = udev_device_get_parent(device); | 93 udev_device *parent = udev_device_get_parent(device); |
85 if (!parent) { | 94 if (!parent) { |
86 return; | 95 return; |
87 } | 96 } |
88 | 97 |
89 const char* hid_id = udev_device_get_property_value(parent, kHIDID); | 98 const char* hid_id = udev_device_get_property_value(parent, kHIDID); |
90 if (!hid_id) | 99 if (!hid_id) |
91 return; | 100 return; |
92 | 101 |
93 std::vector<std::string> parts; | 102 std::vector<std::string> parts; |
94 base::SplitString(hid_id, ':', &parts); | 103 base::SplitString(hid_id, ':', &parts); |
95 if (parts.size() != 3) { | 104 if (parts.size() != 3) { |
96 return; | 105 return; |
97 } | 106 } |
98 | 107 |
99 if (HexStringToUInt(base::StringPiece(parts[1]), &int_property)) { | 108 if (HexStringToUInt(base::StringPiece(parts[1]), &int_property)) { |
100 device_info.vendor_id = int_property; | 109 device_info->vendor_id = int_property; |
101 } | 110 } |
102 | 111 |
103 if (HexStringToUInt(base::StringPiece(parts[2]), &int_property)) { | 112 if (HexStringToUInt(base::StringPiece(parts[2]), &int_property)) { |
104 device_info.product_id = int_property; | 113 device_info->product_id = int_property; |
105 } | 114 } |
106 | 115 |
107 str_property = udev_device_get_property_value(parent, kHIDUnique); | 116 str_property = udev_device_get_property_value(parent, kHIDUnique); |
108 if (str_property != NULL) | 117 if (str_property != NULL) |
109 device_info.serial_number = str_property; | 118 device_info->serial_number = str_property; |
110 | 119 |
111 str_property = udev_device_get_property_value(parent, kHIDName); | 120 str_property = udev_device_get_property_value(parent, kHIDName); |
112 if (str_property != NULL) | 121 if (str_property != NULL) |
113 device_info.product_name = str_property; | 122 device_info->product_name = str_property; |
114 | 123 |
115 const std::string dev_node = udev_device_get_devnode(device); | 124 const std::string dev_node = udev_device_get_devnode(device); |
| 125 #if defined(OS_CHROMEOS) |
| 126 // ChromeOS builds on non-ChromeOS machines (dev) should not attempt to |
| 127 // use permission broker. |
| 128 if (base::SysInfo::IsRunningOnChromeOS()) { |
| 129 chromeos::PermissionBrokerClient* client = |
| 130 chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); |
| 131 DCHECK(client) << "Could not get permission broker client."; |
| 132 if (!client) { |
| 133 return; |
| 134 } |
| 135 ui_message_loop_->PostTask( |
| 136 FROM_HERE, |
| 137 base::Bind(&chromeos::PermissionBrokerClient::RequestPathAccess, |
| 138 base::Unretained(client), |
| 139 dev_node, |
| 140 -1, |
| 141 base::Bind(&HidServiceLinux::OnRequestAccessComplete, |
| 142 weak_factory_.GetWeakPtr(), |
| 143 dev_node, |
| 144 base::Passed(&device_info)))); |
| 145 } else { |
| 146 OnRequestAccessComplete(dev_node, device_info.Pass(), true); |
| 147 } |
| 148 #else |
| 149 OnRequestAccessComplete(dev_node, device_info.Pass(), true); |
| 150 #endif // defined(OS_CHROMEOS) |
| 151 } |
| 152 |
| 153 void HidServiceLinux::OnDeviceRemoved(udev_device* device) { |
| 154 const char* device_path = udev_device_get_syspath(device);; |
| 155 if (device_path) |
| 156 RemoveDevice(device_path); |
| 157 } |
| 158 |
| 159 void HidServiceLinux::OnRequestAccessComplete( |
| 160 const std::string& path, |
| 161 scoped_ptr<HidDeviceInfo> device_info, |
| 162 bool success) { |
116 const int flags = base::File::FLAG_OPEN | base::File::FLAG_READ; | 163 const int flags = base::File::FLAG_OPEN | base::File::FLAG_READ; |
117 | 164 base::File device_file(base::FilePath(path), flags); |
118 base::File device_file(base::FilePath(dev_node), flags); | |
119 if (!device_file.IsValid()) { | 165 if (!device_file.IsValid()) { |
120 LOG(ERROR) << "Cannot open '" << dev_node << "': " | 166 LOG(ERROR) << "Cannot open '" << path << "': " |
121 << base::File::ErrorToString(device_file.error_details()); | 167 << base::File::ErrorToString(device_file.error_details()); |
122 return; | 168 return; |
123 } | 169 } |
124 | 170 |
125 int desc_size = 0; | 171 int desc_size = 0; |
126 int res = ioctl(device_file.GetPlatformFile(), HIDIOCGRDESCSIZE, &desc_size); | 172 int res = ioctl(device_file.GetPlatformFile(), HIDIOCGRDESCSIZE, &desc_size); |
127 if (res < 0) { | 173 if (res < 0) { |
128 PLOG(ERROR) << "Failed to get report descriptor size"; | 174 PLOG(ERROR) << "Failed to get report descriptor size"; |
129 device_file.Close(); | 175 device_file.Close(); |
130 return; | 176 return; |
131 } | 177 } |
132 | 178 |
133 hidraw_report_descriptor rpt_desc; | 179 hidraw_report_descriptor rpt_desc; |
134 rpt_desc.size = desc_size; | 180 rpt_desc.size = desc_size; |
135 | 181 |
136 res = ioctl(device_file.GetPlatformFile(), HIDIOCGRDESC, &rpt_desc); | 182 res = ioctl(device_file.GetPlatformFile(), HIDIOCGRDESC, &rpt_desc); |
137 if (res < 0) { | 183 if (res < 0) { |
138 PLOG(ERROR) << "Failed to get report descriptor"; | 184 PLOG(ERROR) << "Failed to get report descriptor"; |
139 device_file.Close(); | 185 device_file.Close(); |
140 return; | 186 return; |
141 } | 187 } |
142 | 188 |
143 device_file.Close(); | 189 device_file.Close(); |
144 | 190 |
145 HidReportDescriptor report_descriptor(rpt_desc.value, rpt_desc.size); | 191 HidReportDescriptor report_descriptor(rpt_desc.value, rpt_desc.size); |
146 report_descriptor.GetDetails(&device_info.collections, | 192 report_descriptor.GetDetails(&device_info->collections, |
147 &device_info.max_input_report_size, | 193 &device_info->max_input_report_size, |
148 &device_info.max_output_report_size, | 194 &device_info->max_output_report_size, |
149 &device_info.max_feature_report_size); | 195 &device_info->max_feature_report_size); |
150 | 196 |
151 AddDevice(device_info); | 197 AddDevice(*device_info); |
152 } | |
153 | |
154 void HidServiceLinux::OnDeviceRemoved(udev_device* device) { | |
155 const char* device_path = udev_device_get_syspath(device);; | |
156 if (device_path) | |
157 RemoveDevice(device_path); | |
158 } | 198 } |
159 | 199 |
160 } // namespace device | 200 } // namespace device |
OLD | NEW |