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

Commit f3da9b6c authored by Tomasz Wasilczyk's avatar Tomasz Wasilczyk Committed by chrisweir
Browse files

Simplify bus configuration.

Previous bus configuration struct was meant for flexibility, but it
turned out that the only dimension that flexibility would go was a
serial number parameter. Let's rotate that configuration matrix by 90
degrees and just go a straightforward route of discriminating against
interface type.

Test: VTS
Bug: 135918744
Change-Id: I08967d0f78c998b0582958eb51bd387f9dbe15fe
parent e0e455f2
Loading
Loading
Loading
Loading
+75 −76
Original line number Diff line number Diff line
@@ -27,51 +27,22 @@ package android.hardware.automotive.can@1.0;
 */
interface ICanController {
    /**
     * Type of an interface, a mean to express the domain of device address.
     * Type of an interface, an equivalent to BusConfig::InterfaceId
     * union discriminator. Defines a number of specific standard hardware
     * families and a generic catch-all type of {@see INDEXED}.
     */
    enum InterfaceType : uint8_t {
        /**
         * Virtual SocketCAN interface.
         *
         * The address is an interface name, such as vcan0. If the interface
         * doesn't exist, HAL server must create it.
         *
         * Valid InterfaceIdentifier types:
         *  - address.
         */
        /** Virtual SocketCAN interface. */
        VIRTUAL,

        /**
         * Native SocketCAN interface.
         *
         * The address is an interface name, such as can0.
         *
         * Valid InterfaceIdentifier types:
         *  - address;
         *  - serialno.
         */
        /** Native SocketCAN interface. */
        SOCKETCAN,

        /**
         * Serial-based interface.
         *
         * The address is a patch to a device, such as /dev/ttyUSB0.
         *
         * Valid InterfaceIdentifier types:
         *  - address;
         *  - serialno.
         */
        /** Serial line CAN interface. */
        SLCAN,

        /**
         * Proprietary interface, specific to the hardware system Android
         * is running on. Instead of using address field, the interface is
         * addressed with 0-based index.
         *
         * Valid InterfaceIdentifier types:
         *  - index
         */
        INDEXED
        /** Proprietary, device-specific interface. */
        INDEXED,
    };

    enum Result : uint8_t {
@@ -92,10 +63,10 @@ interface ICanController {
        NOT_SUPPORTED,

        /**
         * Provided address (interface name, device path) doesn't exist or there
         * is no device with a given serial no.
         * Provided interface ID (index, name, device path) doesn't exist or
         * there is no device with a given serial number.
         */
        BAD_ADDRESS,
        BAD_INTERFACE_ID,

        /** Provided bit rate is not supported by the hardware. */
        BAD_BITRATE,
@@ -106,49 +77,76 @@ interface ICanController {
     *
     * ISO TP and CAN FD are currently not supported.
     */
    struct BusConfiguration {
    struct BusConfig {
        /**
         * Name under which ICanBus HIDL service should be published.
         *
         * It must consist of only alphanumeric characters and underscore
         * (a-z, A-Z, 0-9, '_'), at least 1 and at most 32 characters long.
         *
         * This field is *not* meant to distinguish between hardware interfaces
         * nor preselect parameters like bitrate. The only intended side-effect
         * of changing it should be a different ICanBus HIDL service name and
         * the HIDL service should make no assumptions on its contents.
         */
        string name;

        /**
         * Type of the hardware (or virtual) CAN interface.
         * Hardware interface configuration.
         *
         * This union's discriminator has an equivalent enum
         * {@see InterfaceType} to express compatibility via
         * getSupportedInterfaceTypes().
         */
        InterfaceType iftype;

        /**
         * Identification of hardware interface to configure.
        safe_union InterfaceId {
            /** Virtual SocketCAN interface. */
            struct Virtual {
                /** Interface name, such as vcan0. If the interface doesn't
                 * exist, HAL server must create it.
                 */
        safe_union InterfaceIdentifier {
                string ifname;
            } virtualif;

            /** Native SocketCAN interface. */
            safe_union Socketcan {
                /** Interface name, such as can0. */
                string ifname;
                /**
             * Interface name or other mean of identification of the specific
             * interface port. Syntax depends on {@see iftype}, for details
             * {@see InterfaceType}.
                 * Alternatively to providing {@see ifname}, one may provide a
                 * list of interface serial number suffixes. If there happens to
                 * be a device (like USB2CAN) with a matching serial number
                 * suffix, the HAL service will have to select it.
                 *
                 * Client may utilize this in two ways: by matching against the
                 * entire serial number, or the last few characters (usually
                 * one). The former is better for small-scale test deployments
                 * (with just a handful of vehicles), the latter is good for
                 * larger scale (where a small suffix list may support large
                 * test fleet).
                 */
            string address;
                vec<string> serialno;
            } socketcan;

            /** Serial line CAN interface. */
            safe_union Slcan {
                /** Path to a device, such as /dev/ttyUSB0. */
                string ttyname;
                /**
             * Numerical identifier of interface, used for InterfaceType#INDEXED.
                 * List of interface serial number suffixes.
                 * {@see Socketcan::serialno}
                 */
            uint8_t index;
                vec<string> serialno;
            } slcan;

            /**
             * Alternatively to providing {@see address}, one may provide a list
             * of interface serial number suffixes. If there happens to be
             * a device (like USB2CAN) with a matching serial number suffix,
             * it gets selected.
             * Proprietary, device-specific interface.
             *
             * Client may utilize this in two ways: by matching against the
             * entire serial number, or the last few characters (usually one).
             * The former is better for small-scale test deployments (with just
             * a handful of vehicles), the latter is good for larger scale
             * (where a small suffix list may support large test fleet).
             * Non-SocketCAN interfaces should use this variant.
             */
            vec<string> serialno;
            struct Indexed {
                /** Interface number, 0-based. */
                uint8_t index;
            } indexed;
        } interfaceId;

        /**
@@ -156,7 +154,8 @@ interface ICanController {
         *
         * Typical bit rates are: 100000, 125000, 250000, 500000.
         *
         * For virtual interfaces this value is ignored.
         * For {@see interfaceId#virtual} and pre-configured
         * {@see interfaceId#indexed} interfaces this value is ignored.
         */
        uint32_t bitrate;
    };
@@ -164,17 +163,17 @@ interface ICanController {
    /**
     * Fetches the list of interface types supported by this HAL server.
     *
     * @return iftypes The list of supported interface types
     * @return iftypes The list of supported interface types.
     */
    getSupportedInterfaceTypes() generates (vec<InterfaceType> iftypes);

    /**
     * Bring up the CAN interface and publish ICanBus server instance.
     *
     * @param config Configuration of the CAN interface
     * @param config Configuration of the CAN interface.
     * @return result OK if the operation succeeded; error code otherwise.
     */
    upInterface(BusConfiguration config) generates (Result result);
    upInterface(BusConfig config) generates (Result result);

    /**
     * Unpublish ICanBus server instance and bring down the CAN interface.
@@ -182,9 +181,9 @@ interface ICanController {
     * In case of failure, at least the ICanBus server instance must be
     * unpublished and resources freed on best-effort basis.
     *
     * @param name Name of the interface (@see BusConfiguration#name} to
     * bring down
     * @return success true in case of success, false otherwise
     * @param name Name of the interface (@see BusConfig#name} to
     * bring down.
     * @return success true in case of success, false otherwise.
     */
    downInterface(string name) generates (bool success);
};
+1 −1
Original line number Diff line number Diff line
@@ -124,7 +124,7 @@ ICanController::Result CanBus::up() {
    if (!isUp.has_value()) {
        // preUp() should prepare the interface (either create or make sure it's there)
        LOG(ERROR) << "Interface " << mIfname << " didn't get prepared";
        return ICanController::Result::BAD_ADDRESS;
        return ICanController::Result::BAD_INTERFACE_ID;
    }

    if (!*isUp && !netdevice::up(mIfname)) {
+1 −1
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ CanBusNative::CanBusNative(const std::string& ifname, uint32_t bitrate)
ICanController::Result CanBusNative::preUp() {
    if (!netdevice::exists(mIfname)) {
        LOG(ERROR) << "Interface " << mIfname << " doesn't exist";
        return ICanController::Result::BAD_ADDRESS;
        return ICanController::Result::BAD_INTERFACE_ID;
    }

    if (mBitrate == 0) {
+1 −1
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ ICanController::Result CanBusSlcan::preUp() {
    mFd = base::unique_fd(open(mUartName.c_str(), O_RDWR | O_NONBLOCK | O_NOCTTY));
    if (!mFd.ok()) {
        LOG(ERROR) << "SLCAN Failed to open " << mUartName << ": " << strerror(errno);
        return ICanController::Result::BAD_ADDRESS;
        return ICanController::Result::BAD_INTERFACE_ID;
    }

    // If the device is already up, update the iface name in our CanBusSlcan object
+17 −18
Original line number Diff line number Diff line
@@ -27,7 +27,8 @@

namespace android::hardware::automotive::can::V1_0::implementation {

using IfaceIdDisc = ICanController::BusConfiguration::InterfaceIdentifier::hidl_discriminator;
using IfId = ICanController::BusConfig::InterfaceId;
using IfIdDisc = ICanController::BusConfig::InterfaceId::hidl_discriminator;

Return<void> CanController::getSupportedInterfaceTypes(getSupportedInterfaceTypes_cb _hidl_cb) {
    _hidl_cb({ICanController::InterfaceType::VIRTUAL, ICanController::InterfaceType::SOCKETCAN,
@@ -40,8 +41,7 @@ static bool isValidName(const std::string& name) {
    return std::regex_match(name, nameRE);
}

Return<ICanController::Result> CanController::upInterface(
        const ICanController::BusConfiguration& config) {
Return<ICanController::Result> CanController::upInterface(const ICanController::BusConfig& config) {
    LOG(VERBOSE) << "Attempting to bring interface up: " << toString(config);

    std::lock_guard<std::mutex> lck(mCanBusesGuard);
@@ -58,24 +58,23 @@ Return<ICanController::Result> CanController::upInterface(

    sp<CanBus> busService;

    if (config.iftype == ICanController::InterfaceType::SOCKETCAN) {
        // TODO(b/135918744): support serialno
        if (config.interfaceId.getDiscriminator() == IfaceIdDisc::address) {
            busService = new CanBusNative(config.interfaceId.address(), config.bitrate);
    if (config.interfaceId.getDiscriminator() == IfIdDisc::socketcan) {
        // TODO(b/142654031): support serialno
        auto& socketcan = config.interfaceId.socketcan();
        if (socketcan.getDiscriminator() == IfId::Socketcan::hidl_discriminator::ifname) {
            busService = new CanBusNative(socketcan.ifname(), config.bitrate);
        } else {
            return ICanController::Result::BAD_ADDRESS;
        }
    } else if (config.iftype == ICanController::InterfaceType::VIRTUAL) {
        if (config.interfaceId.getDiscriminator() == IfaceIdDisc::address) {
            busService = new CanBusVirtual(config.interfaceId.address());
        } else {
            return ICanController::Result::BAD_ADDRESS;
        }
    } else if (config.iftype == ICanController::InterfaceType::SLCAN) {
        if (config.interfaceId.getDiscriminator() == IfaceIdDisc::address) {
            busService = new CanBusSlcan(config.interfaceId.address(), config.bitrate);
            return ICanController::Result::BAD_INTERFACE_ID;
        }
    } else if (config.interfaceId.getDiscriminator() == IfIdDisc::virtualif) {
        busService = new CanBusVirtual(config.interfaceId.virtualif().ifname);
    } else if (config.interfaceId.getDiscriminator() == IfIdDisc::slcan) {
        // TODO(b/142654031): support serialno
        auto& slcan = config.interfaceId.slcan();
        if (slcan.getDiscriminator() == IfId::Slcan::hidl_discriminator::ttyname) {
            busService = new CanBusSlcan(slcan.ttyname(), config.bitrate);
        } else {
            return ICanController::Result::BAD_ADDRESS;
            return ICanController::Result::BAD_INTERFACE_ID;
        }
    } else {
        return ICanController::Result::NOT_SUPPORTED;
Loading