blob: 4af831b9b877190a0e9504075ad10a626e01795c [file] [log] [blame]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Bluetooth helper to detect USB disconnect events on bluetooth controller.
// Such an event indicates a low-level transport error or a controller failure
// that caused it to remove itself from the bus.
#include <iostream>
#include <unistd.h>
#include <vector>
#include <base/files/file_util.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <re2/re2.h>
namespace {
constexpr char kBtIdentifierRegex[] = "usb(.*)bluetooth";
constexpr char kLogCommand[] = "croslog";
std::vector<std::string> GetBtUsbIdentifiers() {
const base::FilePath symbolic_hci_path("/sys/class/bluetooth/hci0");
base::FilePath resolved_path;
std::string matched_value;
std::vector<std::string> entries;
if (!base::PathExists(symbolic_hci_path) || !base::IsLink(symbolic_hci_path))
return entries;
if (!base::ReadSymbolicLink(symbolic_hci_path, &resolved_path))
return entries;
if (!RE2::PartialMatch(resolved_path.MaybeAsASCII(), kBtIdentifierRegex,
&matched_value))
return entries;
entries = base::SplitString(matched_value, "/", base::KEEP_WHITESPACE,
base::SPLIT_WANT_NONEMPTY);
return entries;
}
int LocateUsbDisconnects() {
std::vector<std::string> identifiers = GetBtUsbIdentifiers();
if (identifiers.empty())
return 0;
// A USB disconnect event will show up in the logs with the format:
// "usb 1-3: USB disconnect", but there are more than one identifier that may
// match to the bluetooth device. Here, we construct a grep string to pass to
// croslog to locate any relevant USB disconnect events.
std::string grep_string =
"--grep=usb (" + base::JoinString(identifiers, "|") + "): USB disconnect";
return execlp(kLogCommand, kLogCommand, "--show-cursor=false", "--boot",
grep_string.c_str(), nullptr);
}
} // namespace
int main() {
return LocateUsbDisconnects();
}