Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Side by Side Diff: device/usb/usb_device_impl.cc

Issue 980023002: Move device/usb classes from the FILE thread to UI thread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/usb/usb_device_impl.h" 5 #include "device/usb/usb_device_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/location.h" 10 #include "base/location.h"
11 #include "base/sequenced_task_runner.h"
11 #include "base/single_thread_task_runner.h" 12 #include "base/single_thread_task_runner.h"
12 #include "base/stl_util.h" 13 #include "base/stl_util.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/thread_task_runner_handle.h" 14 #include "base/thread_task_runner_handle.h"
16 #include "components/device_event_log/device_event_log.h" 15 #include "components/device_event_log/device_event_log.h"
17 #include "device/usb/usb_context.h" 16 #include "device/usb/usb_context.h"
18 #include "device/usb/usb_descriptors.h" 17 #include "device/usb/usb_descriptors.h"
19 #include "device/usb/usb_device_handle_impl.h" 18 #include "device/usb/usb_device_handle_impl.h"
20 #include "device/usb/usb_error.h" 19 #include "device/usb/usb_error.h"
21 #include "third_party/libusb/src/libusb/libusb.h" 20 #include "third_party/libusb/src/libusb/libusb.h"
22 21
23 #if defined(OS_CHROMEOS) 22 #if defined(OS_CHROMEOS)
24 #include "base/sys_info.h" 23 #include "base/sys_info.h"
25 #include "chromeos/dbus/dbus_thread_manager.h" 24 #include "chromeos/dbus/dbus_thread_manager.h"
26 #include "chromeos/dbus/permission_broker_client.h" 25 #include "chromeos/dbus/permission_broker_client.h"
27 #endif // defined(OS_CHROMEOS) 26 #endif // defined(OS_CHROMEOS)
28 27
29 #if defined(USE_UDEV)
30 #include "device/udev_linux/scoped_udev.h"
31 #endif // defined(USE_UDEV)
32
33 namespace device { 28 namespace device {
34 29
35 namespace { 30 namespace {
36 31
37 #if defined(OS_CHROMEOS)
38 void OnRequestUsbAccessReplied(
39 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
40 const base::Callback<void(bool success)>& callback,
41 bool success) {
42 task_runner->PostTask(FROM_HERE, base::Bind(callback, success));
43 }
44 #endif // defined(OS_CHROMEOS)
45
46 UsbEndpointDirection GetDirection( 32 UsbEndpointDirection GetDirection(
47 const libusb_endpoint_descriptor* descriptor) { 33 const libusb_endpoint_descriptor* descriptor) {
48 switch (descriptor->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) { 34 switch (descriptor->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) {
49 case LIBUSB_ENDPOINT_IN: 35 case LIBUSB_ENDPOINT_IN:
50 return USB_DIRECTION_INBOUND; 36 return USB_DIRECTION_INBOUND;
51 case LIBUSB_ENDPOINT_OUT: 37 case LIBUSB_ENDPOINT_OUT:
52 return USB_DIRECTION_OUTBOUND; 38 return USB_DIRECTION_OUTBOUND;
53 default: 39 default:
54 NOTREACHED(); 40 NOTREACHED();
55 return USB_DIRECTION_INBOUND; 41 return USB_DIRECTION_INBOUND;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 default: 86 default:
101 NOTREACHED(); 87 NOTREACHED();
102 return USB_USAGE_DATA; 88 return USB_USAGE_DATA;
103 } 89 }
104 } 90 }
105 91
106 } // namespace 92 } // namespace
107 93
108 UsbDeviceImpl::UsbDeviceImpl( 94 UsbDeviceImpl::UsbDeviceImpl(
109 scoped_refptr<UsbContext> context, 95 scoped_refptr<UsbContext> context,
110 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
111 PlatformUsbDevice platform_device, 96 PlatformUsbDevice platform_device,
112 uint16 vendor_id, 97 uint16 vendor_id,
113 uint16 product_id, 98 uint16 product_id,
114 uint32 unique_id) 99 uint32 unique_id,
115 : UsbDevice(vendor_id, product_id, unique_id), 100 const base::string16& manufacturer_string,
101 const base::string16& product_string,
102 const base::string16& serial_number,
103 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
104 : UsbDevice(vendor_id,
105 product_id,
106 unique_id,
107 manufacturer_string,
108 product_string,
109 serial_number),
116 platform_device_(platform_device), 110 platform_device_(platform_device),
117 context_(context), 111 context_(context),
118 ui_task_runner_(ui_task_runner) { 112 task_runner_(base::ThreadTaskRunnerHandle::Get()),
113 blocking_task_runner_(blocking_task_runner) {
119 CHECK(platform_device) << "platform_device cannot be NULL"; 114 CHECK(platform_device) << "platform_device cannot be NULL";
120 libusb_ref_device(platform_device); 115 libusb_ref_device(platform_device);
121 RefreshConfiguration(); 116 RefreshConfiguration();
122 #if defined(USE_UDEV)
123 ScopedUdevPtr udev(udev_new());
124 ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev.get()));
125
126 udev_enumerate_add_match_subsystem(enumerate.get(), "usb");
127 if (udev_enumerate_scan_devices(enumerate.get()) != 0) {
128 return;
129 }
130 std::string bus_number =
131 base::IntToString(libusb_get_bus_number(platform_device));
132 std::string device_address =
133 base::IntToString(libusb_get_device_address(platform_device));
134 udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate.get());
135 for (udev_list_entry* i = devices; i != NULL;
136 i = udev_list_entry_get_next(i)) {
137 ScopedUdevDevicePtr device(
138 udev_device_new_from_syspath(udev.get(), udev_list_entry_get_name(i)));
139 if (device) {
140 const char* value = udev_device_get_sysattr_value(device.get(), "busnum");
141 if (!value || bus_number != value) {
142 continue;
143 }
144 value = udev_device_get_sysattr_value(device.get(), "devnum");
145 if (!value || device_address != value) {
146 continue;
147 }
148
149 #if defined(OS_CHROMEOS)
150 value = udev_device_get_devnode(device.get());
151 if (value) {
152 devnode_ = value;
153 }
154 #endif
155 value = udev_device_get_sysattr_value(device.get(), "manufacturer");
156 if (value) {
157 manufacturer_ = base::UTF8ToUTF16(value);
158 }
159 value = udev_device_get_sysattr_value(device.get(), "product");
160 if (value) {
161 product_ = base::UTF8ToUTF16(value);
162 }
163 value = udev_device_get_sysattr_value(device.get(), "serial");
164 if (value) {
165 serial_number_ = base::UTF8ToUTF16(value);
166 }
167 break;
168 }
169 }
170 #else
171 strings_cached_ = false;
172 #endif
173 } 117 }
174 118
175 UsbDeviceImpl::~UsbDeviceImpl() { 119 UsbDeviceImpl::~UsbDeviceImpl() {
176 // The destructor must be safe to call from any thread. 120 // The destructor must be safe to call from any thread.
177 libusb_unref_device(platform_device_); 121 libusb_unref_device(platform_device_);
178 } 122 }
179 123
180 #if defined(OS_CHROMEOS) 124 #if defined(OS_CHROMEOS)
181 125
182 void UsbDeviceImpl::RequestUsbAccess( 126 void UsbDeviceImpl::RequestUsbAccess(
183 int interface_id, 127 int interface_id,
184 const base::Callback<void(bool success)>& callback) { 128 const base::Callback<void(bool success)>& callback) {
185 DCHECK(thread_checker_.CalledOnValidThread()); 129 DCHECK(thread_checker_.CalledOnValidThread());
186 130
187 // ChromeOS builds on non-ChromeOS machines (dev) should not attempt to 131 // ChromeOS builds on non-ChromeOS machines (dev) should not attempt to
188 // use permission broker. 132 // use permission broker.
189 if (base::SysInfo::IsRunningOnChromeOS()) { 133 if (base::SysInfo::IsRunningOnChromeOS()) {
190 chromeos::PermissionBrokerClient* client = 134 chromeos::PermissionBrokerClient* client =
191 chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); 135 chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient();
192 DCHECK(client) << "Could not get permission broker client."; 136 DCHECK(client) << "Could not get permission broker client.";
193 if (!client) { 137 if (client) {
138 client->RequestPathAccess(devnode_, interface_id, callback);
139 } else {
194 callback.Run(false); 140 callback.Run(false);
195 return;
196 } 141 }
197
198 ui_task_runner_->PostTask(
199 FROM_HERE,
200 base::Bind(&chromeos::PermissionBrokerClient::RequestPathAccess,
201 base::Unretained(client),
202 devnode_,
203 interface_id,
204 base::Bind(&OnRequestUsbAccessReplied,
205 base::ThreadTaskRunnerHandle::Get(),
206 callback)));
207 } else { 142 } else {
208 // Not really running on Chrome OS, declare success. 143 // Not really running on Chrome OS, declare success.
209 callback.Run(true); 144 callback.Run(true);
210 } 145 }
211 } 146 }
212 147
213 #endif 148 #endif
214 149
215 scoped_refptr<UsbDeviceHandle> UsbDeviceImpl::Open() { 150 void UsbDeviceImpl::Open(const OpenCallback& callback) {
216 DCHECK(thread_checker_.CalledOnValidThread()); 151 DCHECK(thread_checker_.CalledOnValidThread());
217 PlatformUsbDeviceHandle handle; 152 blocking_task_runner_->PostTask(
218 const int rv = libusb_open(platform_device_, &handle); 153 FROM_HERE,
219 if (LIBUSB_SUCCESS == rv) { 154 base::Bind(&UsbDeviceImpl::OpenOnBlockingThread, this, callback));
220 scoped_refptr<UsbDeviceHandleImpl> device_handle =
221 new UsbDeviceHandleImpl(context_, this, handle);
222 handles_.push_back(device_handle);
223 return device_handle;
224 } else {
225 USB_LOG(EVENT) << "Failed to open device: "
226 << ConvertPlatformUsbErrorToString(rv);
227 return NULL;
228 }
229 } 155 }
230 156
231 bool UsbDeviceImpl::Close(scoped_refptr<UsbDeviceHandle> handle) { 157 bool UsbDeviceImpl::Close(scoped_refptr<UsbDeviceHandle> handle) {
232 DCHECK(thread_checker_.CalledOnValidThread()); 158 DCHECK(thread_checker_.CalledOnValidThread());
233 159
234 for (HandlesVector::iterator it = handles_.begin(); it != handles_.end(); 160 for (HandlesVector::iterator it = handles_.begin(); it != handles_.end();
235 ++it) { 161 ++it) {
236 if (it->get() == handle.get()) { 162 if (it->get() == handle.get()) {
237 (*it)->InternalClose(); 163 (*it)->InternalClose();
238 handles_.erase(it); 164 handles_.erase(it);
239 return true; 165 return true;
240 } 166 }
241 } 167 }
242 return false; 168 return false;
243 } 169 }
244 170
245 const UsbConfigDescriptor* UsbDeviceImpl::GetConfiguration() { 171 const UsbConfigDescriptor* UsbDeviceImpl::GetConfiguration() {
246 DCHECK(thread_checker_.CalledOnValidThread()); 172 DCHECK(thread_checker_.CalledOnValidThread());
247 return configuration_.get(); 173 return configuration_.get();
248 } 174 }
249 175
250 bool UsbDeviceImpl::GetManufacturer(base::string16* manufacturer) {
251 DCHECK(thread_checker_.CalledOnValidThread());
252
253 #if !defined(USE_UDEV)
254 if (!strings_cached_) {
255 CacheStrings();
256 }
257 #endif
258
259 *manufacturer = manufacturer_;
260 return !manufacturer_.empty();
261 }
262
263 bool UsbDeviceImpl::GetProduct(base::string16* product) {
264 DCHECK(thread_checker_.CalledOnValidThread());
265
266 #if !defined(USE_UDEV)
267 if (!strings_cached_) {
268 CacheStrings();
269 }
270 #endif
271
272 *product = product_;
273 return !product_.empty();
274 }
275
276 bool UsbDeviceImpl::GetSerialNumber(base::string16* serial_number) {
277 DCHECK(thread_checker_.CalledOnValidThread());
278
279 #if !defined(USE_UDEV)
280 if (!strings_cached_) {
281 CacheStrings();
282 }
283 #endif
284
285 *serial_number = serial_number_;
286 return !serial_number_.empty();
287 }
288
289 void UsbDeviceImpl::OnDisconnect() { 176 void UsbDeviceImpl::OnDisconnect() {
290 DCHECK(thread_checker_.CalledOnValidThread()); 177 DCHECK(thread_checker_.CalledOnValidThread());
291 178
292 // Swap the list of handles into a local variable because closing all open 179 // Swap the list of handles into a local variable because closing all open
293 // handles may release the last reference to this object. 180 // handles may release the last reference to this object.
294 HandlesVector handles; 181 HandlesVector handles;
295 swap(handles, handles_); 182 swap(handles, handles_);
296 183
297 for (const scoped_refptr<UsbDeviceHandleImpl>& handle : handles_) { 184 for (const scoped_refptr<UsbDeviceHandleImpl>& handle : handles_) {
298 handle->InternalClose(); 185 handle->InternalClose();
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 } 244 }
358 } 245 }
359 246
360 configuration_->extra_data = std::vector<uint8_t>( 247 configuration_->extra_data = std::vector<uint8_t>(
361 platform_config->extra, 248 platform_config->extra,
362 platform_config->extra + platform_config->extra_length); 249 platform_config->extra + platform_config->extra_length);
363 250
364 libusb_free_config_descriptor(platform_config); 251 libusb_free_config_descriptor(platform_config);
365 } 252 }
366 253
367 #if !defined(USE_UDEV) 254 void UsbDeviceImpl::OpenOnBlockingThread(const OpenCallback& callback) {
368 void UsbDeviceImpl::CacheStrings() { 255 PlatformUsbDeviceHandle handle;
256 const int rv = libusb_open(platform_device_, &handle);
257 if (LIBUSB_SUCCESS == rv) {
258 task_runner_->PostTask(
259 FROM_HERE, base::Bind(&UsbDeviceImpl::Opened, this, handle, callback));
260 } else {
261 USB_LOG(EVENT) << "Failed to open device: "
262 << ConvertPlatformUsbErrorToString(rv);
263 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr));
264 }
265 }
266
267 void UsbDeviceImpl::Opened(PlatformUsbDeviceHandle platform_handle,
268 const OpenCallback& callback) {
369 DCHECK(thread_checker_.CalledOnValidThread()); 269 DCHECK(thread_checker_.CalledOnValidThread());
370 // This is a non-blocking call as libusb has the descriptor in memory. 270 scoped_refptr<UsbDeviceHandleImpl> device_handle = new UsbDeviceHandleImpl(
371 libusb_device_descriptor desc; 271 context_, this, platform_handle, blocking_task_runner_);
372 const int rv = libusb_get_device_descriptor(platform_device_, &desc); 272 handles_.push_back(device_handle);
373 if (rv == LIBUSB_SUCCESS) { 273 callback.Run(device_handle);
374 scoped_refptr<UsbDeviceHandle> device_handle = Open();
375 if (device_handle.get()) {
376 if (desc.iManufacturer != 0) {
377 device_handle->GetStringDescriptor(desc.iManufacturer, &manufacturer_);
378 }
379 if (desc.iProduct != 0) {
380 device_handle->GetStringDescriptor(desc.iProduct, &product_);
381 }
382 if (desc.iSerialNumber != 0) {
383 device_handle->GetStringDescriptor(desc.iSerialNumber, &serial_number_);
384 }
385 device_handle->Close();
386 } else {
387 USB_LOG(EVENT) << "Failed to open device to cache string descriptors.";
388 }
389 } else {
390 USB_LOG(EVENT)
391 << "Failed to read device descriptor to cache string descriptors: "
392 << ConvertPlatformUsbErrorToString(rv);
393 }
394 strings_cached_ = true;
395 } 274 }
396 #endif // !defined(USE_UDEV)
397 275
398 } // namespace device 276 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698