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

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

Powered by Google App Engine
This is Rietveld 408576698