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

Commit 4763857c authored by Tomasz Wasilczyk's avatar Tomasz Wasilczyk Committed by Android (Google) Code Review
Browse files

Merge changes from topic "canhal"

* changes:
  Add ICanController BAD_SERVICE_NAME error
  Simplify bus configuration.
parents fca2707a 793fab0b
Loading
Loading
Loading
Loading
+81 −76
Original line number Original line Diff line number Diff line
@@ -27,51 +27,22 @@ package android.hardware.automotive.can@1.0;
 */
 */
interface ICanController {
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 {
    enum InterfaceType : uint8_t {
        /**
        /** Virtual SocketCAN interface. */
         * 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,
        VIRTUAL,


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


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


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


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


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


        /** Provided bit rate is not supported by the hardware. */
        /** Provided bit rate is not supported by the hardware. */
        BAD_BITRATE,
        BAD_BITRATE,

        /**
         * Provided service name ({@see BusConfig#name}) either has invalid
         * format or is not listed in device manifest file.
         */
        BAD_SERVICE_NAME,
    };
    };


    /**
    /**
@@ -106,49 +83,76 @@ interface ICanController {
     *
     *
     * ISO TP and CAN FD are currently not supported.
     * ISO TP and CAN FD are currently not supported.
     */
     */
    struct BusConfiguration {
    struct BusConfig {
        /**
        /**
         * Name under which ICanBus HIDL service should be published.
         * Name under which ICanBus HIDL service should be published.
         *
         *
         * It must consist of only alphanumeric characters and underscore
         * It must consist of only alphanumeric characters and underscore
         * (a-z, A-Z, 0-9, '_'), at least 1 and at most 32 characters long.
         * (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;
        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;
        safe_union InterfaceId {

            /** Virtual SocketCAN interface. */
        /**
            struct Virtual {
         * Identification of hardware interface to configure.
                /** 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
                 * Alternatively to providing {@see ifname}, one may provide a
             * interface port. Syntax depends on {@see iftype}, for details
                 * list of interface serial number suffixes. If there happens to
             * {@see InterfaceType}.
                 * 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
             * Proprietary, device-specific interface.
             * of interface serial number suffixes. If there happens to be
             * a device (like USB2CAN) with a matching serial number suffix,
             * it gets selected.
             *
             *
             * Client may utilize this in two ways: by matching against the
             * Non-SocketCAN interfaces should use this variant.
             * 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).
             */
             */
            vec<string> serialno;
            struct Indexed {
                /** Interface number, 0-based. */
                uint8_t index;
            } indexed;
        } interfaceId;
        } interfaceId;


        /**
        /**
@@ -156,7 +160,8 @@ interface ICanController {
         *
         *
         * Typical bit rates are: 100000, 125000, 250000, 500000.
         * 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;
        uint32_t bitrate;
    };
    };
@@ -164,17 +169,17 @@ interface ICanController {
    /**
    /**
     * Fetches the list of interface types supported by this HAL server.
     * 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);
    getSupportedInterfaceTypes() generates (vec<InterfaceType> iftypes);


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


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


    if (mBitrate == 0) {
    if (mBitrate == 0) {
+1 −1
Original line number Original line 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));
    mFd = base::unique_fd(open(mUartName.c_str(), O_RDWR | O_NONBLOCK | O_NOCTTY));
    if (!mFd.ok()) {
    if (!mFd.ok()) {
        LOG(ERROR) << "SLCAN Failed to open " << mUartName << ": " << strerror(errno);
        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
    // If the device is already up, update the iface name in our CanBusSlcan object
+19 −20
Original line number Original line Diff line number Diff line
@@ -27,7 +27,8 @@


namespace android::hardware::automotive::can::V1_0::implementation {
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) {
Return<void> CanController::getSupportedInterfaceTypes(getSupportedInterfaceTypes_cb _hidl_cb) {
    _hidl_cb({ICanController::InterfaceType::VIRTUAL, ICanController::InterfaceType::SOCKETCAN,
    _hidl_cb({ICanController::InterfaceType::VIRTUAL, ICanController::InterfaceType::SOCKETCAN,
@@ -40,15 +41,14 @@ static bool isValidName(const std::string& name) {
    return std::regex_match(name, nameRE);
    return std::regex_match(name, nameRE);
}
}


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


    std::lock_guard<std::mutex> lck(mCanBusesGuard);
    std::lock_guard<std::mutex> lck(mCanBusesGuard);


    if (!isValidName(config.name)) {
    if (!isValidName(config.name)) {
        LOG(ERROR) << "Bus name " << config.name << " is invalid";
        LOG(ERROR) << "Bus name " << config.name << " is invalid";
        return ICanController::Result::UNKNOWN_ERROR;
        return ICanController::Result::BAD_SERVICE_NAME;
    }
    }


    if (mCanBuses.find(config.name) != mCanBuses.end()) {
    if (mCanBuses.find(config.name) != mCanBuses.end()) {
@@ -58,24 +58,23 @@ Return<ICanController::Result> CanController::upInterface(


    sp<CanBus> busService;
    sp<CanBus> busService;


    if (config.iftype == ICanController::InterfaceType::SOCKETCAN) {
    if (config.interfaceId.getDiscriminator() == IfIdDisc::socketcan) {
        // TODO(b/135918744): support serialno
        // TODO(b/142654031): support serialno
        if (config.interfaceId.getDiscriminator() == IfaceIdDisc::address) {
        auto& socketcan = config.interfaceId.socketcan();
            busService = new CanBusNative(config.interfaceId.address(), config.bitrate);
        if (socketcan.getDiscriminator() == IfId::Socketcan::hidl_discriminator::ifname) {
            busService = new CanBusNative(socketcan.ifname(), config.bitrate);
        } else {
        } else {
            return ICanController::Result::BAD_ADDRESS;
            return ICanController::Result::BAD_INTERFACE_ID;
        }
        }
    } else if (config.iftype == ICanController::InterfaceType::VIRTUAL) {
    } else if (config.interfaceId.getDiscriminator() == IfIdDisc::virtualif) {
        if (config.interfaceId.getDiscriminator() == IfaceIdDisc::address) {
        busService = new CanBusVirtual(config.interfaceId.virtualif().ifname);
            busService = new CanBusVirtual(config.interfaceId.address());
    } else if (config.interfaceId.getDiscriminator() == IfIdDisc::slcan) {
        } else {
        // TODO(b/142654031): support serialno
            return ICanController::Result::BAD_ADDRESS;
        auto& slcan = config.interfaceId.slcan();
        }
        if (slcan.getDiscriminator() == IfId::Slcan::hidl_discriminator::ttyname) {
    } else if (config.iftype == ICanController::InterfaceType::SLCAN) {
            busService = new CanBusSlcan(slcan.ttyname(), config.bitrate);
        if (config.interfaceId.getDiscriminator() == IfaceIdDisc::address) {
            busService = new CanBusSlcan(config.interfaceId.address(), config.bitrate);
        } else {
        } else {
            return ICanController::Result::BAD_ADDRESS;
            return ICanController::Result::BAD_INTERFACE_ID;
        }
        }
    } else {
    } else {
        return ICanController::Result::NOT_SUPPORTED;
        return ICanController::Result::NOT_SUPPORTED;
@@ -91,7 +90,7 @@ Return<ICanController::Result> CanController::upInterface(
        if (!busService->down()) {
        if (!busService->down()) {
            LOG(WARNING) << "Failed to bring down CAN bus that failed to register";
            LOG(WARNING) << "Failed to bring down CAN bus that failed to register";
        }
        }
        return ICanController::Result::UNKNOWN_ERROR;
        return ICanController::Result::BAD_SERVICE_NAME;
    }
    }


    mCanBuses[config.name] = busService;
    mCanBuses[config.name] = busService;
Loading