blob: 9029eb93cc6779b93d8fa3d6d22bd55c95bad952 [file] [log] [blame]
Ben Chan120c11c2012-09-10 23:10:18 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Ben Chan0a389a62011-10-03 15:02:34 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Chan5ccd9fe2013-11-13 18:28:27 -08005#include "cros-disks/usb_device_info.h"
Ben Chan0a389a62011-10-03 15:02:34 -07006
7#include <vector>
8
Qijiang Fan713061e2021-03-08 15:45:12 +09009#include <base/check.h>
Ben Chan0a389a62011-10-03 15:02:34 -070010#include <base/logging.h>
Ben Chan97e20d42014-02-05 18:38:07 -080011#include <base/strings/string_split.h>
12#include <base/strings/string_util.h>
Ben Chan0a389a62011-10-03 15:02:34 -070013
Ben Chan5ccd9fe2013-11-13 18:28:27 -080014#include "cros-disks/file_reader.h"
François Degros8b4e31e2019-07-29 11:39:19 +100015#include "cros-disks/quote.h"
Ben Chan0a389a62011-10-03 15:02:34 -070016
Ben Chan0a389a62011-10-03 15:02:34 -070017namespace cros_disks {
18
19// A data structure for holding information of a USB device.
20struct USBDeviceEntry {
21 DeviceMediaType media_type;
22};
23
Ben Chanfc77d712019-06-20 12:45:56 -070024USBDeviceInfo::USBDeviceInfo() = default;
Ben Chan0a389a62011-10-03 15:02:34 -070025
Ben Chanfc77d712019-06-20 12:45:56 -070026USBDeviceInfo::~USBDeviceInfo() = default;
Ben Chan0a389a62011-10-03 15:02:34 -070027
28DeviceMediaType USBDeviceInfo::GetDeviceMediaType(
Ben Chan213c6d92019-04-10 16:21:52 -070029 const std::string& vendor_id, const std::string& product_id) const {
Ben Chan0a389a62011-10-03 15:02:34 -070030 CHECK(!vendor_id.empty()) << "Invalid vendor ID";
31 CHECK(!product_id.empty()) << "Invalid product ID";
32
Ben Chan213c6d92019-04-10 16:21:52 -070033 std::string id = vendor_id + ":" + product_id;
34 std::map<std::string, USBDeviceEntry>::const_iterator map_iterator =
35 entries_.find(id);
Ben Chan0a389a62011-10-03 15:02:34 -070036 if (map_iterator != entries_.end())
37 return map_iterator->second.media_type;
Ben Chan6d0b2722011-11-18 08:24:14 -080038 return DEVICE_MEDIA_USB;
Ben Chan0a389a62011-10-03 15:02:34 -070039}
40
Ben Chan213c6d92019-04-10 16:21:52 -070041bool USBDeviceInfo::RetrieveFromFile(const std::string& path) {
Ben Chan0a389a62011-10-03 15:02:34 -070042 entries_.clear();
43
44 FileReader reader;
Ben Chan213c6d92019-04-10 16:21:52 -070045 if (!reader.Open(base::FilePath(path))) {
François Degros8b4e31e2019-07-29 11:39:19 +100046 LOG(ERROR) << "Cannot retrieve USB device info from " << quote(path) << "";
Ben Chan0a389a62011-10-03 15:02:34 -070047 return false;
48 }
49
Ben Chan213c6d92019-04-10 16:21:52 -070050 std::string line;
Ben Chan0a389a62011-10-03 15:02:34 -070051 while (reader.ReadLine(&line)) {
Ben Chan120c11c2012-09-10 23:10:18 -070052 if (IsLineSkippable(line))
Ben Chan0a389a62011-10-03 15:02:34 -070053 continue;
54
Ben Chan213c6d92019-04-10 16:21:52 -070055 std::vector<std::string> tokens = base::SplitString(
56 line, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
Ben Chan0a389a62011-10-03 15:02:34 -070057 if (tokens.size() >= 2) {
58 USBDeviceEntry& entry = entries_[tokens[0]];
59 entry.media_type = ConvertToDeviceMediaType(tokens[1]);
60 }
61 }
62 return true;
63}
64
Ben Chan213c6d92019-04-10 16:21:52 -070065bool USBDeviceInfo::GetVendorAndProductName(const std::string& ids_file,
66 const std::string& vendor_id,
67 const std::string& product_id,
68 std::string* vendor_name,
69 std::string* product_name) {
Ben Chan120c11c2012-09-10 23:10:18 -070070 vendor_name->clear();
71 product_name->clear();
72
73 FileReader reader;
Ben Chan213c6d92019-04-10 16:21:52 -070074 if (!reader.Open(base::FilePath(ids_file))) {
François Degros8b4e31e2019-07-29 11:39:19 +100075 LOG(ERROR) << "Cannot retrieve USB identifier database at "
76 << quote(ids_file);
Ben Chan120c11c2012-09-10 23:10:18 -070077 return false;
78 }
79
80 bool found_vendor = false;
Ben Chan213c6d92019-04-10 16:21:52 -070081 std::string line;
Ben Chan120c11c2012-09-10 23:10:18 -070082 while (reader.ReadLine(&line)) {
83 if (IsLineSkippable(line))
84 continue;
85
Ben Chan213c6d92019-04-10 16:21:52 -070086 std::string id, name;
Ben Chan120c11c2012-09-10 23:10:18 -070087 // If the target vendor ID is found, search for a matching product ID.
88 if (found_vendor) {
Ben Chande0e3f62017-09-26 06:28:39 -070089 if (line[0] == '\t' && ExtractIdAndName(line.substr(1), &id, &name)) {
Ben Chan120c11c2012-09-10 23:10:18 -070090 if (id == product_id) {
91 *product_name = name;
92 break;
93 }
94 continue;
95 }
96
97 // If the line does not contain any product info, assume a new
98 // section has started and no product info will be found for the
99 // target ID. Return immediately.
100 break;
101 }
102
103 // Skip forward until the target vendor ID is found.
104 if (ExtractIdAndName(line, &id, &name)) {
105 if (id == vendor_id) {
106 *vendor_name = name;
107 found_vendor = true;
108 }
109 }
110 }
111
112 return found_vendor;
113}
114
Ben Chan0a389a62011-10-03 15:02:34 -0700115DeviceMediaType USBDeviceInfo::ConvertToDeviceMediaType(
Ben Chan213c6d92019-04-10 16:21:52 -0700116 const std::string& str) const {
Ben Chan0a389a62011-10-03 15:02:34 -0700117 if (str == "sd") {
Ben Chan6d0b2722011-11-18 08:24:14 -0800118 return DEVICE_MEDIA_SD;
Ben Chan0a389a62011-10-03 15:02:34 -0700119 } else if (str == "mobile") {
Ben Chan6d0b2722011-11-18 08:24:14 -0800120 return DEVICE_MEDIA_MOBILE;
Ben Chan0a389a62011-10-03 15:02:34 -0700121 } else {
Ben Chan6d0b2722011-11-18 08:24:14 -0800122 return DEVICE_MEDIA_USB;
Ben Chan0a389a62011-10-03 15:02:34 -0700123 }
124}
125
Ben Chan213c6d92019-04-10 16:21:52 -0700126bool USBDeviceInfo::IsLineSkippable(const std::string& line) const {
127 std::string trimmed_line;
Ben Chan120c11c2012-09-10 23:10:18 -0700128 // Trim only ASCII whitespace for now.
Ben Chanaf25ddb2014-05-21 18:32:47 -0700129 base::TrimWhitespaceASCII(line, base::TRIM_ALL, &trimmed_line);
Alex Vakulenkoe50371c2016-01-20 16:06:19 -0800130 return trimmed_line.empty() ||
131 base::StartsWith(trimmed_line, "#", base::CompareCase::SENSITIVE);
Ben Chan120c11c2012-09-10 23:10:18 -0700132}
133
Ben Chan213c6d92019-04-10 16:21:52 -0700134bool USBDeviceInfo::ExtractIdAndName(const std::string& line,
135 std::string* id,
136 std::string* name) const {
Ben Chande0e3f62017-09-26 06:28:39 -0700137 if ((line.length() > 6) && base::IsHexDigit(line[0]) &&
138 base::IsHexDigit(line[1]) && base::IsHexDigit(line[2]) &&
139 base::IsHexDigit(line[3]) && (line[4] == ' ') && (line[5] == ' ')) {
Alex Vakulenkoe50371c2016-01-20 16:06:19 -0800140 *id = base::ToLowerASCII(line.substr(0, 4));
Ben Chan120c11c2012-09-10 23:10:18 -0700141 *name = line.substr(6);
142 return true;
143 }
144 return false;
145}
146
Ben Chan0a389a62011-10-03 15:02:34 -0700147} // namespace cros_disks