Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33ce7505 authored by chrisweir's avatar chrisweir
Browse files

CAN Configurator Service

Configurator service for the CAN HAL and extracting some of the CAN HAL
configuration logic into a library for the various tools to share.

Bug: 142653776
Test: Manual
Change-Id: Id33871da851bcb442a7f851919f713ec913830ff
parent 4763857c
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@ cc_binary {
    header_libs: [
        "android.hardware.automotive.can@hidl-utils-lib",
    ],
    static_libs: [
        "android.hardware.automotive.can@libcanhaltools",
    ],
}

cc_binary {
@@ -42,6 +45,9 @@ cc_binary {
    header_libs: [
        "android.hardware.automotive.can@hidl-utils-lib",
    ],
    static_libs: [
        "android.hardware.automotive.can@libcanhaltools",
    ],
}

cc_binary {
@@ -54,4 +60,7 @@ cc_binary {
        "android.hardware.automotive.can@1.0",
        "libhidlbase",
    ],
    static_libs: [
        "android.hardware.automotive.can@libcanhaltools",
    ],
}
+4 −20
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <android/hardware/automotive/can/1.0/ICanController.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <hidl-utils/hidl-utils.h>
#include <libcanhaltools/libcanhaltools.h>

#include <iostream>
#include <string>
@@ -41,34 +42,17 @@ static void usage() {
    std::cerr << " bus name - name under which ICanBus will be published" << std::endl;
}

static hidl_vec<hidl_string> getControlServices() {
    auto manager = hidl::manager::V1_2::IServiceManager::getService();
    hidl_vec<hidl_string> services;
    manager->listManifestByInterface(ICanController::descriptor, hidl_utils::fill(&services));
    if (services.size() == 0) {
        std::cerr << "No ICanController services registered (missing privileges?)" << std::endl;
        exit(-1);
    }
    return services;
}

static bool isSupported(sp<ICanController> ctrl, ICanController::InterfaceType iftype) {
    hidl_vec<ICanController::InterfaceType> supported;
    if (!ctrl->getSupportedInterfaceTypes(hidl_utils::fill(&supported)).isOk()) return false;
    return supported.contains(iftype);
}

static int up(const std::string& busName, ICanController::InterfaceType type,
              const std::string& interface, uint32_t bitrate) {
    bool anySupported = false;
    for (auto&& service : getControlServices()) {
    for (auto&& service : libcanhaltools::getControlServices()) {
        auto ctrl = ICanController::getService(service);
        if (ctrl == nullptr) {
            std::cerr << "Couldn't open ICanController/" << service;
            continue;
        }

        if (!isSupported(ctrl, type)) continue;
        if (!libcanhaltools::isSupported(ctrl, type)) continue;
        anySupported = true;

        ICanController::BusConfig config = {};
@@ -111,7 +95,7 @@ static int up(const std::string& busName, ICanController::InterfaceType type,
}

static int down(const std::string& busName) {
    for (auto&& service : getControlServices()) {
    for (auto&& service : libcanhaltools::getControlServices()) {
        auto ctrl = ICanController::getService(service);
        if (ctrl == nullptr) continue;

+34 −0
Original line number Diff line number Diff line
//
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

cc_binary {
    name: "canhalconfigurator",
    init_rc: ["canhalconfigurator.rc"],
    defaults: ["android.hardware.automotive.can@defaults"],
    srcs: [
        "canhalconfigurator.cpp",
        "canprototools.cpp",
    ],
    shared_libs: [
        "android.hardware.automotive.can@1.0",
        "libhidlbase",
        "libprotobuf-cpp-full",
    ],
    static_libs: [
        "android.hardware.automotive.can@1.x-config-format",
        "android.hardware.automotive.can@libcanhaltools",
    ],
}
+103 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "canbus_config.pb.h"
#include "canprototools.h"

#include <android-base/logging.h>
#include <android/hardware/automotive/can/1.0/ICanController.h>
#include <libcanhaltools/libcanhaltools.h>

#include <chrono>
#include <thread>

namespace android::hardware::automotive::can {

using ICanController = V1_0::ICanController;

/**
 * Takes output from parsed protobuf config and uses it to configure the CAN HAL.
 *
 * \param pb_cfg is an instance of the autogenerated protobuf object for our configuration.
 * \return boolean status, true on success, false on failure.
 */
static bool processPbCfg(const config::CanBusConfig& pb_cfg) {
    for (auto const& bus : pb_cfg.buses()) {
        if (bus.name().empty()) {
            LOG(ERROR) << "Invalid config: Bus config must have a valid name field";
            return false;
        }

        LOG(INFO) << "Configure " << bus.name();
        auto bus_cfg = config::fromPbBus(bus);
        if (!bus_cfg.has_value()) {
            return false;
        }

        // TODO(149405589): remove this sleep and associated includes.
        std::this_thread::sleep_for(std::chrono::seconds(1));
        if (libcanhaltools::configureIface(*bus_cfg) != ICanController::Result::OK) {
            LOG(ERROR) << "No controller supports " << bus.name() << std::endl;
            // TODO(149405589): add retry logic in case a bus fails to come up.
            continue;
        }
        LOG(INFO) << bus.name() << " has been successfully configured!";
    }
    return true;
}

/**
 * This kicks off the CAN HAL configuration process. This starts the following:
 *     1. Reading the config file
 *     2. Setting up CAN buses
 *     3. Handling services
 * \param filepath is a string specifying the absolute path of the config file
 * \return boolean status, true on success, false on failure
 */
static bool configuratorStart(const std::string& filepath) {
    base::SetDefaultTag("CanConfigurator");

    auto pb_cfg = config::parseConfigFile(filepath);
    if (!pb_cfg.has_value()) {
        return false;
    }

    // process the rest of the config file data and configure the CAN buses.
    if (!processPbCfg(*pb_cfg)) {
        return false;
    }
    LOG(INFO) << "CAN HAL has been configured!";
    return true;
}

}  // namespace android::hardware::automotive::can

int main(int argc, char* argv[]) {
    std::string config_filepath = "/etc/canbus_config.pb";

    // allow for CLI specification of a config file.
    if (argc == 2) {
        config_filepath = argv[1];
    } else if (argc > 2) {
        std::cerr << "usage: " << argv[0] << " [optional config filepath]";
        return 1;
    }

    if (!::android::hardware::automotive::can::configuratorStart(config_filepath)) {
        return 1;
    }
    return 0;
}
+3 −0
Original line number Diff line number Diff line
service canhalconfigurator /system/bin/canhalconfigurator
  class core
  oneshot
Loading