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
3 // found in the LICENSE file.
5 #include "device/serial/serial_device_enumerator_linux.h"
7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h"
14 const char kSerialSubsystem
[] = "tty";
16 const char kHostPathKey
[] = "DEVNAME";
17 const char kHostBusKey
[] = "ID_BUS";
18 const char kVendorIDKey
[] = "ID_VENDOR_ID";
19 const char kProductIDKey
[] = "ID_MODEL_ID";
20 const char kProductNameKey
[] = "ID_MODEL";
25 scoped_ptr
<SerialDeviceEnumerator
> SerialDeviceEnumerator::Create() {
26 return scoped_ptr
<SerialDeviceEnumerator
>(new SerialDeviceEnumeratorLinux());
29 SerialDeviceEnumeratorLinux::SerialDeviceEnumeratorLinux() {
30 udev_
.reset(udev_new());
33 SerialDeviceEnumeratorLinux::~SerialDeviceEnumeratorLinux() {}
35 mojo::Array
<serial::DeviceInfoPtr
> SerialDeviceEnumeratorLinux::GetDevices() {
36 mojo::Array
<serial::DeviceInfoPtr
> devices(0);
37 ScopedUdevEnumeratePtr
enumerate(udev_enumerate_new(udev_
.get()));
39 LOG(ERROR
) << "Serial device enumeration failed.";
40 return devices
.Pass();
42 if (udev_enumerate_add_match_subsystem(enumerate
.get(), kSerialSubsystem
)) {
43 LOG(ERROR
) << "Serial device enumeration failed.";
44 return devices
.Pass();
46 if (udev_enumerate_scan_devices(enumerate
.get())) {
47 LOG(ERROR
) << "Serial device enumeration failed.";
48 return devices
.Pass();
51 udev_list_entry
* entry
= udev_enumerate_get_list_entry(enumerate
.get());
52 for (; entry
!= NULL
; entry
= udev_list_entry_get_next(entry
)) {
53 ScopedUdevDevicePtr
device(udev_device_new_from_syspath(
54 udev_
.get(), udev_list_entry_get_name(entry
)));
55 // TODO(rockot): There may be a better way to filter serial devices here,
56 // but it's not clear what that would be. Udev will list lots of virtual
57 // devices with no real endpoint to back them anywhere. The presence of
58 // a bus identifier (e.g., "pci" or "usb") seems to be a good heuristic
59 // for detecting actual devices.
61 udev_device_get_property_value(device
.get(), kHostPathKey
);
62 const char* bus
= udev_device_get_property_value(device
.get(), kHostBusKey
);
63 if (path
!= NULL
&& bus
!= NULL
) {
64 serial::DeviceInfoPtr
info(serial::DeviceInfo::New());
67 const char* vendor_id
=
68 udev_device_get_property_value(device
.get(), kVendorIDKey
);
69 const char* product_id
=
70 udev_device_get_property_value(device
.get(), kProductIDKey
);
71 const char* product_name
=
72 udev_device_get_property_value(device
.get(), kProductNameKey
);
75 if (vendor_id
&& base::HexStringToUInt(vendor_id
, &int_value
)) {
76 info
->vendor_id
= int_value
;
77 info
->has_vendor_id
= true;
79 if (product_id
&& base::HexStringToUInt(product_id
, &int_value
)) {
80 info
->product_id
= int_value
;
81 info
->has_product_id
= true;
84 info
->display_name
= product_name
;
85 devices
.push_back(info
.Pass());
88 return devices
.Pass();