mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
AIDL CAN HAL
CAN HAL: now HIDL-free with 100% of your daily value of AIDL. Bug: 170405615 Test: atest CanControllerAidlTest Test: manually test slcan and socketcan hardware Change-Id: I06bbb1379f4385e89757722c0276009b54cc7255
This commit is contained in:
40
automotive/can/aidl/Android.bp
Normal file
40
automotive/can/aidl/Android.bp
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Copyright (C) 2022 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.
|
||||
//
|
||||
|
||||
package {
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
aidl_interface {
|
||||
name: "android.hardware.automotive.can",
|
||||
vendor_available: true,
|
||||
srcs: ["android/hardware/automotive/can/*.aidl"],
|
||||
stability: "vintf",
|
||||
host_supported: true,
|
||||
backend: {
|
||||
java: {
|
||||
enabled: false,
|
||||
},
|
||||
rust: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.automotive.can;
|
||||
@VintfStability
|
||||
parcelable BusConfig {
|
||||
String name;
|
||||
android.hardware.automotive.can.BusConfig.InterfaceId interfaceId;
|
||||
int bitrate;
|
||||
union InterfaceId {
|
||||
android.hardware.automotive.can.VirtualInterface virtualif;
|
||||
android.hardware.automotive.can.NativeInterface nativeif;
|
||||
android.hardware.automotive.can.SlcanInterface slcan;
|
||||
android.hardware.automotive.can.IndexedInterface indexed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.automotive.can;
|
||||
@VintfStability
|
||||
interface ICanController {
|
||||
android.hardware.automotive.can.InterfaceType[] getSupportedInterfaceTypes();
|
||||
String getInterfaceName(in String busName);
|
||||
String upBus(in android.hardware.automotive.can.BusConfig config);
|
||||
void downBus(in String name);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.automotive.can;
|
||||
@VintfStability
|
||||
parcelable IndexedInterface {
|
||||
byte index;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.automotive.can;
|
||||
@Backing(type="byte") @VintfStability
|
||||
enum InterfaceType {
|
||||
VIRTUAL = 0,
|
||||
NATIVE = 1,
|
||||
SLCAN = 2,
|
||||
INDEXED = 3,
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.automotive.can;
|
||||
@VintfStability
|
||||
parcelable NativeInterface {
|
||||
android.hardware.automotive.can.NativeInterface.InterfaceId interfaceId;
|
||||
union InterfaceId {
|
||||
String ifname;
|
||||
String[] serialno;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.automotive.can;
|
||||
@Backing(type="int") @VintfStability
|
||||
enum Result {
|
||||
OK = 0,
|
||||
UNKNOWN_ERROR = 1,
|
||||
INVALID_STATE = 2,
|
||||
NOT_SUPPORTED = 3,
|
||||
BAD_INTERFACE_ID = 4,
|
||||
BAD_BITRATE = 5,
|
||||
BAD_BUS_NAME = 6,
|
||||
INTERFACE_DOWN = 7,
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.automotive.can;
|
||||
@VintfStability
|
||||
parcelable SlcanInterface {
|
||||
android.hardware.automotive.can.SlcanInterface.InterfaceId interfaceId;
|
||||
union InterfaceId {
|
||||
String ttyname;
|
||||
String[] serialno;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.automotive.can;
|
||||
@VintfStability
|
||||
parcelable VirtualInterface {
|
||||
String ifname;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
package android.hardware.automotive.can;
|
||||
|
||||
import android.hardware.automotive.can.IndexedInterface;
|
||||
import android.hardware.automotive.can.NativeInterface;
|
||||
import android.hardware.automotive.can.SlcanInterface;
|
||||
import android.hardware.automotive.can.VirtualInterface;
|
||||
|
||||
/**
|
||||
* Configuration of the (physical or virtual) CAN bus.
|
||||
*
|
||||
* ISO TP and CAN FD support is dependent upon the hardware.
|
||||
*/
|
||||
@VintfStability
|
||||
parcelable BusConfig {
|
||||
/**
|
||||
* Name by which a given bus may be referenced.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This field represents a more human-friendly name for a CAN bus:
|
||||
* e.x. rather than /some/dev/can1234, "name" might be "BodyCAN" or "CCAN"
|
||||
*/
|
||||
String name;
|
||||
|
||||
/**
|
||||
* Hardware interface configuration.
|
||||
*
|
||||
* This union's discriminator has an equivalent enum {@see InterfaceType} to
|
||||
* express compatibility via getSupportedInterfaceTypes().
|
||||
*/
|
||||
union InterfaceId {
|
||||
/** Virtual SocketCAN interface. */
|
||||
VirtualInterface virtualif;
|
||||
|
||||
/** Native SocketCAN interface. */
|
||||
NativeInterface nativeif;
|
||||
|
||||
/** Serial line CAN interface. */
|
||||
SlcanInterface slcan;
|
||||
|
||||
/**
|
||||
* Proprietary, device-specific interface.
|
||||
*
|
||||
* Non-SocketCAN interfaces should use this variant.
|
||||
*/
|
||||
IndexedInterface indexed;
|
||||
}
|
||||
|
||||
InterfaceId interfaceId;
|
||||
|
||||
/**
|
||||
* Bit rate for CAN communication.
|
||||
*
|
||||
* Typical bit rates are: 100000, 125000, 250000, 500000.
|
||||
*
|
||||
* For {@see interfaceId#virtual} interfaces, this value is ignored.
|
||||
*/
|
||||
int bitrate;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
package android.hardware.automotive.can;
|
||||
|
||||
import android.hardware.automotive.can.BusConfig;
|
||||
import android.hardware.automotive.can.InterfaceType;
|
||||
import android.hardware.automotive.can.Result;
|
||||
|
||||
/**
|
||||
* Represents a CAN controller that's capable of configuring CAN bus interfaces.
|
||||
*
|
||||
* The goal of this service is to configure and manage CAN interfaces.
|
||||
*
|
||||
* Providing an ICanController interface to configure CAN buses is optional.
|
||||
* A system can elect to configure CAN buses manually if the hardware is
|
||||
* dedicated to a specific application.
|
||||
*/
|
||||
@VintfStability
|
||||
interface ICanController {
|
||||
/**
|
||||
* Fetches the list of interface types supported by this HAL server.
|
||||
*
|
||||
* @return iftypes The list of supported interface types.
|
||||
*/
|
||||
InterfaceType[] getSupportedInterfaceTypes();
|
||||
|
||||
/**
|
||||
* Gets the interface name given the name of the bus. This will
|
||||
*
|
||||
* @param busName Name of the CAN bus who's interface name we would like
|
||||
* (e.x. BCAN, CCAN, HS3, BodyCAN, ...)
|
||||
* @return name of the socketcan network interface corresponding to busName
|
||||
* (e.x. can0, vcan5, ...)
|
||||
*/
|
||||
String getInterfaceName(in String busName);
|
||||
|
||||
/**
|
||||
* Bring up a CAN bus.
|
||||
*
|
||||
* @param config Configuration for the CAN bus.
|
||||
* @return name of iface if successful
|
||||
*/
|
||||
String upBus(in BusConfig config);
|
||||
|
||||
/**
|
||||
* Bring down a CAN bus.
|
||||
*
|
||||
* @param name Name of the bus (@see BusConfig#name} to bring down.
|
||||
*/
|
||||
void downBus(in String name);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
package android.hardware.automotive.can;
|
||||
|
||||
@VintfStability
|
||||
parcelable IndexedInterface {
|
||||
/** Interface number, 0-based. */
|
||||
byte index;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
package android.hardware.automotive.can;
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
*/
|
||||
@VintfStability
|
||||
@Backing(type="byte")
|
||||
enum InterfaceType {
|
||||
/** Virtual SocketCAN interface. */
|
||||
VIRTUAL,
|
||||
|
||||
/** Native SocketCAN interface. */
|
||||
NATIVE,
|
||||
|
||||
/** Serial line CAN interface. */
|
||||
SLCAN,
|
||||
|
||||
/** Proprietary, device-specific interface. */
|
||||
INDEXED,
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
package android.hardware.automotive.can;
|
||||
|
||||
@VintfStability
|
||||
parcelable NativeInterface {
|
||||
union InterfaceId {
|
||||
/** Interface name, such as can0. */
|
||||
String ifname;
|
||||
|
||||
/**
|
||||
* 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 locate 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[] serialno;
|
||||
}
|
||||
|
||||
InterfaceId interfaceId;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
package android.hardware.automotive.can;
|
||||
|
||||
/**
|
||||
* Possible error codes (or OK) for ICanController.
|
||||
*/
|
||||
@VintfStability
|
||||
@Backing(type="int")
|
||||
enum Result {
|
||||
OK,
|
||||
|
||||
/**
|
||||
* General error class, if others are not applicable.
|
||||
*/
|
||||
UNKNOWN_ERROR,
|
||||
|
||||
/**
|
||||
* Up request was called out of order (i.e. trying to up the interface
|
||||
* twice).
|
||||
*/
|
||||
INVALID_STATE,
|
||||
|
||||
/** Interface type is not supported. */
|
||||
NOT_SUPPORTED,
|
||||
|
||||
/**
|
||||
* Provided interface ID (index, name, device path) doesn't exist or there
|
||||
* is no device with a given serial number.
|
||||
*/
|
||||
BAD_INTERFACE_ID,
|
||||
|
||||
/** Provided bit rate is not supported by the hardware. */
|
||||
BAD_BITRATE,
|
||||
|
||||
/**
|
||||
* Provided bus name ({@see BusConfig#name}) has invalid format or doesn't exist.
|
||||
*/
|
||||
BAD_BUS_NAME,
|
||||
|
||||
/**
|
||||
* The interface for the bus you are trying to interact with is currently
|
||||
* down. As opposed to INVALID_STATE, this serves to warn the caller
|
||||
* _before_ they attempt an invalid operation.
|
||||
*/
|
||||
INTERFACE_DOWN,
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
package android.hardware.automotive.can;
|
||||
|
||||
@VintfStability
|
||||
parcelable SlcanInterface {
|
||||
union InterfaceId {
|
||||
/** Path to a device, such as /dev/ttyUSB0. */
|
||||
String ttyname;
|
||||
|
||||
/**
|
||||
* List of interface serial number suffixes.
|
||||
* {@see Socketcan::serialno}
|
||||
*/
|
||||
String[] serialno;
|
||||
}
|
||||
|
||||
InterfaceId interfaceId;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
package android.hardware.automotive.can;
|
||||
|
||||
@VintfStability
|
||||
parcelable VirtualInterface {
|
||||
/**
|
||||
* Interface name, such as vcan0. If the interface doesn't
|
||||
* exist, HAL server must create it.
|
||||
*/
|
||||
String ifname;
|
||||
}
|
||||
51
automotive/can/aidl/default/Android.bp
Normal file
51
automotive/can/aidl/default/Android.bp
Normal file
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// Copyright (C) 2022 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.
|
||||
//
|
||||
|
||||
package {
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.automotive.can-service",
|
||||
init_rc: ["android.hardware.automotive.can.rc"],
|
||||
defaults: ["android.hardware.automotive.can@defaults"],
|
||||
vendor: true,
|
||||
relative_install_path: "hw",
|
||||
srcs: [
|
||||
"CanBus.cpp",
|
||||
"CanBusSlcan.cpp",
|
||||
"CanBusNative.cpp",
|
||||
"CanBusVirtual.cpp",
|
||||
"CanController.cpp",
|
||||
"service.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"android.hardware.automotive.can-V1-ndk",
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
],
|
||||
static_libs: [
|
||||
"android.hardware.automotive.can@libnetdevice",
|
||||
"android.hardware.automotive@libc++fs",
|
||||
"libnl++",
|
||||
],
|
||||
vintf_fragments: ["android.hardware.automotive.can.xml"],
|
||||
}
|
||||
93
automotive/can/aidl/default/CanBus.cpp
Normal file
93
automotive/can/aidl/default/CanBus.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2022, 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.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <libnetdevice/libnetdevice.h>
|
||||
|
||||
namespace aidl::android::hardware::automotive::can {
|
||||
|
||||
CanBus::CanBus(std::string_view ifname) : mIfname(ifname) {}
|
||||
|
||||
CanBus::~CanBus() {
|
||||
std::lock_guard<std::mutex> lck(mIsUpGuard);
|
||||
CHECK(!mIsUp) << "Interface is still up while being destroyed";
|
||||
}
|
||||
|
||||
Result CanBus::preUp() {
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
bool CanBus::postDown() {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string CanBus::getIfaceName() {
|
||||
return mIfname;
|
||||
}
|
||||
|
||||
Result CanBus::up() {
|
||||
std::lock_guard<std::mutex> lck(mIsUpGuard);
|
||||
|
||||
if (mIsUp) {
|
||||
LOG(WARNING) << "Interface is already up";
|
||||
return Result::INVALID_STATE;
|
||||
}
|
||||
|
||||
const auto preResult = preUp();
|
||||
if (preResult != Result::OK) return preResult;
|
||||
|
||||
const auto isUp = ::android::netdevice::isUp(mIfname);
|
||||
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 Result::BAD_INTERFACE_ID;
|
||||
}
|
||||
|
||||
if (!*isUp && !::android::netdevice::up(mIfname)) {
|
||||
LOG(ERROR) << "Can't bring " << mIfname << " up";
|
||||
return Result::UNKNOWN_ERROR;
|
||||
}
|
||||
mDownAfterUse = !*isUp;
|
||||
|
||||
mIsUp = true;
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
Result CanBus::down() {
|
||||
std::lock_guard<std::mutex> lck(mIsUpGuard);
|
||||
|
||||
if (!mIsUp) {
|
||||
LOG(WARNING) << "Interface is already down";
|
||||
return Result::INVALID_STATE;
|
||||
}
|
||||
mIsUp = false;
|
||||
|
||||
Result success = Result::OK;
|
||||
|
||||
if (mDownAfterUse && !::android::netdevice::down(mIfname)) {
|
||||
LOG(ERROR) << "Can't bring " << mIfname << " down";
|
||||
// don't return yet, let's try to do best-effort cleanup
|
||||
success = Result::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
if (!postDown()) success = Result::UNKNOWN_ERROR;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::automotive::can
|
||||
77
automotive/can/aidl/default/CanBus.h
Normal file
77
automotive/can/aidl/default/CanBus.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2022, 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/automotive/can/Result.h>
|
||||
|
||||
#include <android-base/macros.h>
|
||||
#include <utils/Mutex.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
namespace aidl::android::hardware::automotive::can {
|
||||
|
||||
class CanBus {
|
||||
public:
|
||||
/**
|
||||
* Some interface types (such as SLCAN) don't get an interface name until after being
|
||||
* initialized, hence ifname is optional.
|
||||
*
|
||||
* You MUST ensure mIfname is initialized prior to the completion of preUp().
|
||||
*/
|
||||
CanBus(std::string_view ifname = std::string_view{""});
|
||||
|
||||
virtual ~CanBus();
|
||||
|
||||
Result up();
|
||||
Result down();
|
||||
std::string getIfaceName();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Prepare the SocketCAN interface.
|
||||
*
|
||||
* After calling this method, mIfname network interface is available and ready to be brought up.
|
||||
*
|
||||
* \return true upon success and false upon failure
|
||||
*/
|
||||
virtual Result preUp();
|
||||
|
||||
/**
|
||||
* Cleanup after bringing the interface down.
|
||||
*
|
||||
* This is a counterpart to preUp().
|
||||
*
|
||||
* \return true upon success and false upon failure
|
||||
*/
|
||||
virtual bool postDown();
|
||||
|
||||
/** Network interface name. */
|
||||
std::string mIfname;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Guard for up flag is required to be held for entire time when the interface is being used
|
||||
* because we don't want the interface to be torn down while executing that operation.
|
||||
*/
|
||||
std::mutex mIsUpGuard;
|
||||
bool mIsUp GUARDED_BY(mIsUpGuard) = false;
|
||||
|
||||
bool mDownAfterUse;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::automotive::can
|
||||
54
automotive/can/aidl/default/CanBusNative.cpp
Normal file
54
automotive/can/aidl/default/CanBusNative.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2022, 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 "CanBusNative.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <libnetdevice/can.h>
|
||||
#include <libnetdevice/libnetdevice.h>
|
||||
|
||||
namespace aidl::android::hardware::automotive::can {
|
||||
|
||||
using namespace ::android;
|
||||
|
||||
CanBusNative::CanBusNative(const std::string& ifname, uint32_t bitrate)
|
||||
: CanBus(ifname), mBitrate(bitrate) {}
|
||||
|
||||
Result CanBusNative::preUp() {
|
||||
if (!netdevice::exists(mIfname)) {
|
||||
LOG(ERROR) << "Interface " << mIfname << " doesn't exist";
|
||||
return Result::BAD_INTERFACE_ID;
|
||||
}
|
||||
|
||||
if (mBitrate == 0) {
|
||||
// interface is already up and we just want to register it
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
if (!netdevice::down(mIfname)) {
|
||||
LOG(ERROR) << "Can't bring " << mIfname << " down (to configure it)";
|
||||
return Result::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
if (!netdevice::can::setBitrate(mIfname, mBitrate)) {
|
||||
LOG(ERROR) << "Can't set bitrate " << mBitrate << " for " << mIfname;
|
||||
return Result::BAD_BITRATE;
|
||||
}
|
||||
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::automotive::can
|
||||
33
automotive/can/aidl/default/CanBusNative.h
Normal file
33
automotive/can/aidl/default/CanBusNative.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2022, 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "CanBus.h"
|
||||
|
||||
namespace aidl::android::hardware::automotive::can {
|
||||
|
||||
class CanBusNative : public CanBus {
|
||||
public:
|
||||
CanBusNative(const std::string& ifname, uint32_t bitrate);
|
||||
|
||||
protected:
|
||||
virtual Result preUp() override;
|
||||
|
||||
private:
|
||||
const uint32_t mBitrate;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::automotive::can
|
||||
174
automotive/can/aidl/default/CanBusSlcan.cpp
Normal file
174
automotive/can/aidl/default/CanBusSlcan.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright 2022, 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 "CanBusSlcan.h"
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <libnetdevice/libnetdevice.h>
|
||||
|
||||
#include <linux/serial.h>
|
||||
#include <linux/tty.h>
|
||||
#include <net/if.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace aidl::android::hardware::automotive::can {
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
using namespace ::android::base;
|
||||
|
||||
namespace slcanprotocol {
|
||||
static constexpr std::string_view kOpenCommand = "O\r"sv;
|
||||
static constexpr std::string_view kCloseCommand = "C\r"sv;
|
||||
static constexpr int kSlcanDiscipline = N_SLCAN;
|
||||
static constexpr int kDefaultDiscipline = N_TTY;
|
||||
|
||||
static const std::map<uint32_t, std::string_view> kBitrateCommands = {
|
||||
{10000, "C\rS0\r"sv}, {20000, "C\rS1\r"sv}, {50000, "C\rS2\r"sv},
|
||||
{100000, "C\rS3\r"sv}, {125000, "C\rS4\r"sv}, {250000, "C\rS5\r"sv},
|
||||
{500000, "C\rS6\r"sv}, {800000, "C\rS7\r"sv}, {1000000, "C\rS8\r"sv}};
|
||||
} // namespace slcanprotocol
|
||||
|
||||
/**
|
||||
* Serial Line CAN constructor
|
||||
* \param string uartName - name of slcan device (e.x. /dev/ttyUSB0)
|
||||
* \param uint32_t bitrate - speed of the CAN bus (125k = MSCAN, 500k = HSCAN)
|
||||
*/
|
||||
CanBusSlcan::CanBusSlcan(const std::string& uartName, uint32_t bitrate)
|
||||
: CanBus(), mTtyPath(uartName), kBitrate(bitrate) {}
|
||||
|
||||
/** helper function to update CanBusSlcan object's iface name */
|
||||
Result CanBusSlcan::updateIfaceName(unique_fd& uartFd) {
|
||||
struct ifreq ifrequest = {};
|
||||
/*
|
||||
* Fetching the iface name with an ioctl won't interfere with an open socketCAN iface attached
|
||||
* to this tty. This is important in the event we are trying to register a SLCAN based iface
|
||||
* that has already been configured and brought up.
|
||||
*/
|
||||
if (ioctl(uartFd.get(), SIOCGIFNAME, ifrequest.ifr_name) < 0) {
|
||||
PLOG(ERROR) << "Failed to get the name of the created device";
|
||||
return Result::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
// Update the CanBus object with name that was assigned to it
|
||||
mIfname = ifrequest.ifr_name;
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
Result CanBusSlcan::preUp() {
|
||||
// verify valid bitrate and translate to serial command format
|
||||
std::optional<std::string_view> canBitrateCommand = std::nullopt;
|
||||
if (kBitrate != 0) {
|
||||
const auto lookupIt = slcanprotocol::kBitrateCommands.find(kBitrate);
|
||||
if (lookupIt == slcanprotocol::kBitrateCommands.end()) {
|
||||
return Result::BAD_BITRATE;
|
||||
}
|
||||
canBitrateCommand = lookupIt->second;
|
||||
}
|
||||
|
||||
/* Attempt to open the uart in r/w without blocking or becoming the
|
||||
* controlling terminal */
|
||||
mFd = unique_fd(open(mTtyPath.c_str(), O_RDWR | O_NONBLOCK | O_NOCTTY | O_CLOEXEC));
|
||||
if (!mFd.ok()) {
|
||||
PLOG(ERROR) << "SLCAN Failed to open " << mTtyPath;
|
||||
return Result::BAD_INTERFACE_ID;
|
||||
}
|
||||
|
||||
// If the device is already up, update the iface name in our CanBusSlcan object
|
||||
if (kBitrate == 0) {
|
||||
return updateIfaceName(mFd);
|
||||
}
|
||||
|
||||
// blank terminal settings and pull them from the device
|
||||
struct termios terminalSettings = {};
|
||||
if (tcgetattr(mFd.get(), &terminalSettings) < 0) {
|
||||
PLOG(ERROR) << "Failed to read attrs of" << mTtyPath;
|
||||
return Result::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
// change settings to raw mode
|
||||
cfmakeraw(&terminalSettings);
|
||||
|
||||
// disable software flow control
|
||||
terminalSettings.c_iflag &= ~IXOFF;
|
||||
// enable hardware flow control
|
||||
terminalSettings.c_cflag |= CRTSCTS;
|
||||
|
||||
struct serial_struct serialSettings;
|
||||
// get serial settings
|
||||
if (ioctl(mFd.get(), TIOCGSERIAL, &serialSettings) < 0) {
|
||||
PLOG(ERROR) << "Failed to read serial settings from " << mTtyPath;
|
||||
return Result::UNKNOWN_ERROR;
|
||||
}
|
||||
// set low latency mode
|
||||
serialSettings.flags |= ASYNC_LOW_LATENCY;
|
||||
// apply serial settings
|
||||
if (ioctl(mFd.get(), TIOCSSERIAL, &serialSettings) < 0) {
|
||||
PLOG(ERROR) << "Failed to set low latency mode on " << mTtyPath;
|
||||
return Result::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
/* TCSADRAIN applies settings after we finish writing the rest of our
|
||||
* changes (as opposed to TCSANOW, which changes immediately) */
|
||||
if (tcsetattr(mFd.get(), TCSADRAIN, &terminalSettings) < 0) {
|
||||
PLOG(ERROR) << "Failed to apply terminal settings to " << mTtyPath;
|
||||
return Result::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
// apply speed setting for CAN
|
||||
if (!WriteStringToFd(*canBitrateCommand, mFd)) {
|
||||
PLOG(ERROR) << "Failed to apply CAN bitrate";
|
||||
return Result::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
// TODO(b/144775286): set open flag & support listen only
|
||||
if (!WriteStringToFd(slcanprotocol::kOpenCommand, mFd)) {
|
||||
PLOG(ERROR) << "Failed to set open flag";
|
||||
return Result::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
// set line discipline to slcan
|
||||
if (ioctl(mFd.get(), TIOCSETD, &slcanprotocol::kSlcanDiscipline) < 0) {
|
||||
PLOG(ERROR) << "Failed to set line discipline to slcan";
|
||||
return Result::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
// Update the CanBus object with name that was assigned to it
|
||||
return updateIfaceName(mFd);
|
||||
}
|
||||
|
||||
bool CanBusSlcan::postDown() {
|
||||
// reset the line discipline to TTY mode
|
||||
if (ioctl(mFd.get(), TIOCSETD, &slcanprotocol::kDefaultDiscipline) < 0) {
|
||||
LOG(ERROR) << "Failed to reset line discipline!";
|
||||
return false;
|
||||
}
|
||||
|
||||
// issue the close command
|
||||
if (!WriteStringToFd(slcanprotocol::kCloseCommand, mFd)) {
|
||||
LOG(ERROR) << "Failed to close tty!";
|
||||
return false;
|
||||
}
|
||||
|
||||
// close our unique_fd
|
||||
mFd.reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::automotive::can
|
||||
40
automotive/can/aidl/default/CanBusSlcan.h
Normal file
40
automotive/can/aidl/default/CanBusSlcan.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2022, 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "CanBus.h"
|
||||
|
||||
#include <android-base/unique_fd.h>
|
||||
|
||||
namespace aidl::android::hardware::automotive::can {
|
||||
|
||||
class CanBusSlcan : public CanBus {
|
||||
public:
|
||||
CanBusSlcan(const std::string& uartName, uint32_t bitrate);
|
||||
|
||||
protected:
|
||||
virtual Result preUp() override;
|
||||
virtual bool postDown() override;
|
||||
|
||||
private:
|
||||
Result updateIfaceName(::android::base::unique_fd& uartFd);
|
||||
|
||||
const std::string mTtyPath;
|
||||
const uint32_t kBitrate;
|
||||
::android::base::unique_fd mFd;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::automotive::can
|
||||
52
automotive/can/aidl/default/CanBusVirtual.cpp
Normal file
52
automotive/can/aidl/default/CanBusVirtual.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2022, 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 "CanBusVirtual.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <libnetdevice/libnetdevice.h>
|
||||
|
||||
namespace aidl::android::hardware::automotive::can {
|
||||
|
||||
using namespace ::android;
|
||||
|
||||
CanBusVirtual::CanBusVirtual(const std::string& ifname) : CanBus(ifname) {}
|
||||
|
||||
Result CanBusVirtual::preUp() {
|
||||
if (netdevice::exists(mIfname)) return Result::OK;
|
||||
|
||||
LOG(DEBUG) << "Virtual interface " << mIfname << " doesn't exist, creating...";
|
||||
mWasCreated = true;
|
||||
if (!netdevice::add(mIfname, "vcan")) {
|
||||
LOG(ERROR) << "Can't create vcan interface " << mIfname;
|
||||
return Result::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
bool CanBusVirtual::postDown() {
|
||||
if (mWasCreated) {
|
||||
mWasCreated = false;
|
||||
if (!netdevice::del(mIfname)) {
|
||||
LOG(ERROR) << "Couldn't remove vcan interface " << mIfname;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::automotive::can
|
||||
34
automotive/can/aidl/default/CanBusVirtual.h
Normal file
34
automotive/can/aidl/default/CanBusVirtual.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2022, 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "CanBus.h"
|
||||
|
||||
namespace aidl::android::hardware::automotive::can {
|
||||
|
||||
class CanBusVirtual : public CanBus {
|
||||
public:
|
||||
CanBusVirtual(const std::string& ifname);
|
||||
|
||||
protected:
|
||||
virtual Result preUp() override;
|
||||
virtual bool postDown() override;
|
||||
|
||||
private:
|
||||
bool mWasCreated = false;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::automotive::can
|
||||
333
automotive/can/aidl/default/CanController.cpp
Normal file
333
automotive/can/aidl/default/CanController.cpp
Normal file
@@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright 2022, 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 "CanController.h"
|
||||
|
||||
#include "CanBusNative.h"
|
||||
#include "CanBusSlcan.h"
|
||||
#include "CanBusVirtual.h"
|
||||
|
||||
#include <android-base/format.h>
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include <automotive/filesystem>
|
||||
#include <fstream>
|
||||
#include <regex>
|
||||
|
||||
namespace aidl::android::hardware::automotive::can {
|
||||
|
||||
namespace fs = ::android::hardware::automotive::filesystem;
|
||||
|
||||
namespace fsErrors {
|
||||
static const std::error_code ok;
|
||||
static const std::error_code eperm(EPERM, std::generic_category());
|
||||
static const std::error_code enoent(ENOENT, std::generic_category());
|
||||
static const std::error_code eacces(EACCES, std::generic_category());
|
||||
} // namespace fsErrors
|
||||
|
||||
/* In the /sys/devices tree, there are files called "serial", which contain the serial numbers
|
||||
* for various devices. The exact location inside of this directory is dependent upon the
|
||||
* hardware we are running on, so we have to start from /sys/devices and work our way down. */
|
||||
static const fs::path kDevPath("/sys/devices/");
|
||||
static const std::regex kTtyRe("^tty[A-Z]+[0-9]+$");
|
||||
static constexpr auto kOpts = ~(fs::directory_options::follow_directory_symlink |
|
||||
fs::directory_options::skip_permission_denied);
|
||||
|
||||
constexpr auto ok = &ndk::ScopedAStatus::ok;
|
||||
|
||||
/**
|
||||
* A helper object to associate the interface name and type of a USB to CAN adapter.
|
||||
*/
|
||||
struct UsbCanIface {
|
||||
InterfaceType iftype;
|
||||
std::string ifaceName;
|
||||
};
|
||||
|
||||
static bool isValidName(const std::string& name) {
|
||||
static const std::regex nameRE("^[a-zA-Z0-9_]{1,32}$");
|
||||
return std::regex_match(name, nameRE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a path, get the last element from it.
|
||||
*
|
||||
* \param itrPath - the path we want the last element of
|
||||
* \return - the last element in the path (in string form).
|
||||
*/
|
||||
static std::string getLeaf(const fs::path& itrPath) {
|
||||
/* end() returns an iterator one past the leaf of the path, so we've overshot
|
||||
decrement (--) to go back one to the leaf
|
||||
dereference and now we have our leaf. */
|
||||
return *(--(itrPath.end()));
|
||||
}
|
||||
|
||||
static ndk::ScopedAStatus resultToStatus(Result res, const std::string& msg = "") {
|
||||
if (msg.empty()) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(static_cast<int>(res)));
|
||||
}
|
||||
return ndk::ScopedAStatus(
|
||||
AStatus_fromServiceSpecificErrorWithMessage(static_cast<int>(res), msg.c_str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a UsbCanIface object, get the ifaceName given the serialPath.
|
||||
*
|
||||
* \param serialPath - Absolute path to a "serial" file for a given device in /sys.
|
||||
* \return A populated UsbCanIface. On failure, nullopt is returned.
|
||||
*/
|
||||
static std::optional<UsbCanIface> getIfaceName(const fs::path& serialPath) {
|
||||
std::error_code fsStatus;
|
||||
// Since the path is to a file called "serial", we need to search its parent directory.
|
||||
fs::recursive_directory_iterator fsItr(serialPath.parent_path(), kOpts, fsStatus);
|
||||
if (fsStatus != fsErrors::ok) {
|
||||
LOG(ERROR) << "Failed to open " << serialPath.parent_path();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
for (; fsStatus == fsErrors::ok && fsItr != fs::recursive_directory_iterator();
|
||||
fsItr.increment(fsStatus)) {
|
||||
/* We want either a directory called "net" or a directory that looks like tty<something>, so
|
||||
* skip files. */
|
||||
bool isDir = fsItr->is_directory(fsStatus);
|
||||
if (fsStatus != fsErrors::ok || !isDir) continue;
|
||||
|
||||
std::string currentDir = getLeaf(fsItr->path());
|
||||
if (currentDir == "net") {
|
||||
/* This device is a SocketCAN device. The iface name is the only directory under
|
||||
* net/. Multiple directories under net/ is an error.*/
|
||||
fs::directory_iterator netItr(fsItr->path(), kOpts, fsStatus);
|
||||
if (fsStatus != fsErrors::ok) {
|
||||
LOG(ERROR) << "Failed to open " << fsItr->path() << " to get net name!";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// The leaf of our path should be the interface name.
|
||||
std::string netName = getLeaf(netItr->path());
|
||||
|
||||
// Check if there is more than one item in net/
|
||||
netItr.increment(fsStatus);
|
||||
if (fsStatus != fsErrors::ok) {
|
||||
// It's possible we have a valid net name, but this is most likely an error.
|
||||
LOG(ERROR) << "Failed to verify " << fsItr->path() << " has valid net name!";
|
||||
return std::nullopt;
|
||||
}
|
||||
if (netItr != fs::directory_iterator()) {
|
||||
// There should never be more than one name under net/
|
||||
LOG(ERROR) << "Found more than one net name in " << fsItr->path() << "!";
|
||||
return std::nullopt;
|
||||
}
|
||||
return {{InterfaceType::NATIVE, netName}};
|
||||
} else if (std::regex_match(currentDir, kTtyRe)) {
|
||||
// This device is a USB serial device, and currentDir is the tty name.
|
||||
return {{InterfaceType::SLCAN, "/dev/" + currentDir}};
|
||||
}
|
||||
}
|
||||
|
||||
// check if the loop above exited due to a c++fs error.
|
||||
if (fsStatus != fsErrors::ok) {
|
||||
LOG(ERROR) << "Failed search filesystem: " << fsStatus;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function to read the serial number from a "serial" file in /sys/devices/
|
||||
*
|
||||
* \param serialnoPath - path to the file to read.
|
||||
* \return the serial number, or nullopt on failure.
|
||||
*/
|
||||
static std::optional<std::string> readSerialNo(const std::string& serialnoPath) {
|
||||
std::ifstream serialnoStream(serialnoPath);
|
||||
std::string serialno;
|
||||
if (!serialnoStream.good()) {
|
||||
LOG(ERROR) << "Failed to read serial number from " << serialnoPath;
|
||||
return std::nullopt;
|
||||
}
|
||||
std::getline(serialnoStream, serialno);
|
||||
return serialno;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for USB devices found in /sys/devices/, and attempts to find a device matching the
|
||||
* provided list of serial numbers.
|
||||
*
|
||||
* \param configSerialnos - a list of serial number (suffixes) from the HAL config.
|
||||
* \param iftype - the type of the interface to be located.
|
||||
* \return a matching USB device. On failure, std::nullopt is returned.
|
||||
*/
|
||||
static std::optional<UsbCanIface> findUsbDevice(const std::vector<std::string>& configSerialnos) {
|
||||
std::error_code fsStatus;
|
||||
fs::recursive_directory_iterator fsItr(kDevPath, kOpts, fsStatus);
|
||||
if (fsStatus != fsErrors::ok) {
|
||||
LOG(ERROR) << "Failed to open " << kDevPath;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
for (; fsStatus == fsErrors::ok && fsItr != fs::recursive_directory_iterator();
|
||||
fsItr.increment(fsStatus)) {
|
||||
// We want to find a file called "serial", which is in a directory somewhere. Skip files.
|
||||
bool isDir = fsItr->is_directory(fsStatus);
|
||||
if (fsStatus != fsErrors::ok) {
|
||||
LOG(ERROR) << "Failed check if " << fsStatus;
|
||||
return std::nullopt;
|
||||
}
|
||||
if (!isDir) continue;
|
||||
|
||||
auto serialnoPath = fsItr->path() / "serial";
|
||||
bool isReg = fs::is_regular_file(serialnoPath, fsStatus);
|
||||
|
||||
/* Make sure we have permissions to this directory, ignore enoent, since the file
|
||||
* "serial" may not exist, which is ok. */
|
||||
if (fsStatus == fsErrors::eperm || fsStatus == fsErrors::eacces) {
|
||||
/* This means we don't have access to this directory. If we recurse into it, this
|
||||
* will cause the iterator to loose its state and we'll crash. */
|
||||
fsItr.disable_recursion_pending();
|
||||
continue;
|
||||
}
|
||||
if (fsStatus == fsErrors::enoent) continue;
|
||||
if (fsStatus != fsErrors::ok) {
|
||||
LOG(WARNING) << "An unexpected error occurred while checking for serialno: "
|
||||
<< fsStatus;
|
||||
continue;
|
||||
}
|
||||
if (!isReg) continue;
|
||||
|
||||
// we found a serial number
|
||||
auto serialno = readSerialNo(serialnoPath);
|
||||
if (!serialno.has_value()) continue;
|
||||
|
||||
// see if the serial number exists in the config
|
||||
for (auto&& cfgSn : configSerialnos) {
|
||||
if (serialno->ends_with(std::string(cfgSn))) {
|
||||
auto ifaceInfo = getIfaceName(serialnoPath);
|
||||
if (!ifaceInfo.has_value()) break;
|
||||
return ifaceInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fsStatus != fsErrors::ok) {
|
||||
LOG(ERROR) << "Error searching filesystem: " << fsStatus;
|
||||
return std::nullopt;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus CanController::getSupportedInterfaceTypes(
|
||||
std::vector<InterfaceType>* supportedTypes) {
|
||||
*supportedTypes = {InterfaceType::VIRTUAL, InterfaceType::NATIVE, InterfaceType::SLCAN};
|
||||
return ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus CanController::getInterfaceName(const std::string& busName,
|
||||
std::string* ifaceName) {
|
||||
*ifaceName = {};
|
||||
if (mBusesByName.find(busName) == mBusesByName.end()) {
|
||||
return resultToStatus(Result::BAD_BUS_NAME, fmt::format("{} doesn't exist", busName));
|
||||
}
|
||||
*ifaceName = std::string(mBusesByName[busName]->getIfaceName());
|
||||
return ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus CanController::upBus(const BusConfig& config, std::string* ifaceName) {
|
||||
if (!isValidName(config.name)) {
|
||||
LOG(ERROR) << "Bus name " << config.name << " is invalid";
|
||||
return resultToStatus(Result::BAD_BUS_NAME,
|
||||
fmt::format("{} is not a valid bus name", config.name));
|
||||
} else if (mBusesByName.find(config.name) != mBusesByName.end()) {
|
||||
LOG(ERROR) << "A bus named " << config.name << " already exists!";
|
||||
return resultToStatus(Result::INVALID_STATE,
|
||||
fmt::format("A bus named {} already exists", config.name));
|
||||
}
|
||||
|
||||
if (config.interfaceId.getTag() == BusConfig::InterfaceId::Tag::virtualif) {
|
||||
auto& virtualif = config.interfaceId.get<BusConfig::InterfaceId::Tag::virtualif>();
|
||||
mBusesByName[config.name] = std::make_unique<CanBusVirtual>(virtualif.ifname);
|
||||
}
|
||||
|
||||
else if (config.interfaceId.getTag() == BusConfig::InterfaceId::Tag::nativeif) {
|
||||
auto& nativeif = config.interfaceId.get<BusConfig::InterfaceId::Tag::nativeif>();
|
||||
std::string ifaceName;
|
||||
if (nativeif.interfaceId.getTag() == NativeInterface::InterfaceId::Tag::serialno) {
|
||||
// Configure by serial number.
|
||||
auto selectedDevice = findUsbDevice(
|
||||
nativeif.interfaceId.get<NativeInterface::InterfaceId::Tag::serialno>());
|
||||
// verify the returned device is the correct one
|
||||
if (!selectedDevice.has_value() || selectedDevice->iftype != InterfaceType::NATIVE) {
|
||||
return resultToStatus(
|
||||
Result::BAD_INTERFACE_ID,
|
||||
"Couldn't find a native socketcan device with the given serial number(s)");
|
||||
}
|
||||
ifaceName = selectedDevice->ifaceName;
|
||||
} else {
|
||||
// configure by iface name.
|
||||
ifaceName = nativeif.interfaceId.get<NativeInterface::InterfaceId::Tag::ifname>();
|
||||
}
|
||||
mBusesByName[config.name] = std::make_unique<CanBusNative>(ifaceName, config.bitrate);
|
||||
}
|
||||
|
||||
else if (config.interfaceId.getTag() == BusConfig::InterfaceId::Tag::slcan) {
|
||||
auto& slcanif = config.interfaceId.get<BusConfig::InterfaceId::Tag::slcan>();
|
||||
std::string ttyName;
|
||||
if (slcanif.interfaceId.getTag() == SlcanInterface::InterfaceId::Tag::serialno) {
|
||||
// Configure by serial number.
|
||||
auto selectedDevice = findUsbDevice(
|
||||
slcanif.interfaceId.get<SlcanInterface::InterfaceId::Tag::serialno>());
|
||||
if (!selectedDevice.has_value() || selectedDevice->iftype != InterfaceType::SLCAN) {
|
||||
return resultToStatus(
|
||||
Result::BAD_INTERFACE_ID,
|
||||
"Couldn't find a slcan device with the given serial number(s)");
|
||||
}
|
||||
ttyName = selectedDevice->ifaceName;
|
||||
} else {
|
||||
// Configure by tty name.
|
||||
ttyName = slcanif.interfaceId.get<SlcanInterface::InterfaceId::Tag::ttyname>();
|
||||
}
|
||||
mBusesByName[config.name] = std::make_unique<CanBusSlcan>(ttyName, config.bitrate);
|
||||
}
|
||||
|
||||
else if (config.interfaceId.getTag() == BusConfig::InterfaceId::Tag::indexed) {
|
||||
return resultToStatus(Result::NOT_SUPPORTED,
|
||||
"Indexed devices are not supported in this implementation");
|
||||
} else {
|
||||
// this shouldn't happen.
|
||||
return resultToStatus(Result::UNKNOWN_ERROR, "Unknown interface id type");
|
||||
}
|
||||
|
||||
Result result = mBusesByName[config.name]->up();
|
||||
if (result != Result::OK) {
|
||||
// the bus failed to come up, don't leave a broken entry in the map.
|
||||
mBusesByName.erase(config.name);
|
||||
return resultToStatus(result, fmt::format("CanBus::up failed for {}", config.name));
|
||||
}
|
||||
|
||||
*ifaceName = mBusesByName[config.name]->getIfaceName();
|
||||
return ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus CanController::downBus(const std::string& busName) {
|
||||
if (mBusesByName.find(busName) == mBusesByName.end()) {
|
||||
return resultToStatus(
|
||||
Result::UNKNOWN_ERROR,
|
||||
fmt::format("Couldn't bring down {}, because it doesn't exist", busName));
|
||||
}
|
||||
Result result = mBusesByName[busName]->down();
|
||||
if (result != Result::OK) {
|
||||
return resultToStatus(result, fmt::format("Couldn't bring down {}!", busName));
|
||||
}
|
||||
mBusesByName.erase(busName);
|
||||
return ok();
|
||||
}
|
||||
} // namespace aidl::android::hardware::automotive::can
|
||||
45
automotive/can/aidl/default/CanController.h
Normal file
45
automotive/can/aidl/default/CanController.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2022, 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/automotive/can/BnCanController.h>
|
||||
|
||||
#include "CanBus.h"
|
||||
|
||||
#include <aidl/android/hardware/automotive/can/Result.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace aidl::android::hardware::automotive::can {
|
||||
|
||||
class CanController : public BnCanController {
|
||||
public:
|
||||
ndk::ScopedAStatus getSupportedInterfaceTypes(
|
||||
std::vector<InterfaceType>* supportedTypes) override;
|
||||
|
||||
ndk::ScopedAStatus getInterfaceName(const std::string& busName,
|
||||
std::string* ifaceName) override;
|
||||
|
||||
ndk::ScopedAStatus upBus(const BusConfig& config, std::string* ifaceName) override;
|
||||
|
||||
ndk::ScopedAStatus downBus(const std::string& busName) override;
|
||||
|
||||
private:
|
||||
std::map<std::string, std::unique_ptr<CanBus>> mBusesByName = {};
|
||||
};
|
||||
} // namespace aidl::android::hardware::automotive::can
|
||||
@@ -0,0 +1,5 @@
|
||||
service android.hardware.automotive.can /vendor/bin/hw/android.hardware.automotive.can-service
|
||||
class hal
|
||||
capabilities NET_ADMIN
|
||||
user vehicle_network
|
||||
group system inet
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright (C) 2022 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.
|
||||
-->
|
||||
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.automotive.can</name>
|
||||
<version>1</version>
|
||||
<interface>
|
||||
<name>ICanController</name>
|
||||
<instance>default</instance>
|
||||
</interface>
|
||||
</hal>
|
||||
</manifest>
|
||||
43
automotive/can/aidl/default/service.cpp
Normal file
43
automotive/can/aidl/default/service.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2022, 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 "CanController.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
|
||||
namespace android::hardware::automotive::can {
|
||||
|
||||
using namespace std::string_literals;
|
||||
using ::aidl::android::hardware::automotive::can::CanController;
|
||||
|
||||
extern "C" int main() {
|
||||
base::SetDefaultTag("CanController");
|
||||
base::SetMinimumLogSeverity(base::VERBOSE);
|
||||
|
||||
LOG(VERBOSE) << "Starting up...";
|
||||
auto service = ndk::SharedRefBase::make<CanController>();
|
||||
const auto instance = CanController::descriptor + "/default"s;
|
||||
const auto status = AServiceManager_addService(service->asBinder().get(), instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK) << "Failed to add service " << instance;
|
||||
LOG(VERBOSE) << "Started successfully!";
|
||||
|
||||
ABinderProcess_joinThreadPool();
|
||||
LOG(FATAL) << "CanController exited unexpectedly!";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} // namespace android::hardware::automotive::can
|
||||
43
automotive/can/aidl/default/tools/configurator/Android.bp
Normal file
43
automotive/can/aidl/default/tools/configurator/Android.bp
Normal file
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// Copyright (C) 2022 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.
|
||||
//
|
||||
|
||||
package {
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "canhalconfigurator-aidl",
|
||||
init_rc: ["canhalconfigurator-aidl.rc"],
|
||||
defaults: ["android.hardware.automotive.can@defaults"],
|
||||
srcs: [
|
||||
"canhalconfigurator.cpp",
|
||||
"canprototools.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
"libprotobuf-cpp-full",
|
||||
],
|
||||
static_libs: [
|
||||
"android.hardware.automotive.can-V1-ndk",
|
||||
"android.hardware.automotive.can-aidl-config-format",
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
service canhalconfigurator /system/bin/canhalconfigurator-aidl
|
||||
class core
|
||||
oneshot
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 <aidl/android/hardware/automotive/can/ICanController.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_manager.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
namespace android::hardware::automotive::can {
|
||||
|
||||
using namespace std::string_literals;
|
||||
using ::aidl::android::hardware::automotive::can::ICanController;
|
||||
|
||||
static constexpr std::string_view kDefaultConfigPath = "/etc/canbus_config.pb";
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
auto busCfgMaybe = config::fromPbBus(bus);
|
||||
if (!busCfgMaybe.has_value()) {
|
||||
return false;
|
||||
}
|
||||
auto busCfg = *busCfgMaybe;
|
||||
|
||||
const auto instance = ICanController::descriptor + "/default"s;
|
||||
const auto service = ICanController::fromBinder(
|
||||
ndk::SpAIBinder(AServiceManager_waitForService(instance.c_str())));
|
||||
if (service == nullptr) {
|
||||
LOG(FATAL) << "Can't find CAN HAL! (has it started yet?)";
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG(VERBOSE) << "Bringing up a " << busCfg.name << " @ " << busCfg.bitrate;
|
||||
|
||||
std::string ifaceName;
|
||||
const auto status = service->upBus(busCfg, &ifaceName);
|
||||
if (!status.isOk() && status.getExceptionCode() != EX_SERVICE_SPECIFIC) {
|
||||
LOG(FATAL) << "Binder transaction failed!" << status.getStatus();
|
||||
return false;
|
||||
} else if (!status.isOk()) {
|
||||
LOG(ERROR) << "upBus failed: " << config::resultStringFromStatus(status) << ": "
|
||||
<< status.getMessage();
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG(INFO) << bus.name() << " has been successfully configured on " << ifaceName;
|
||||
}
|
||||
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 pbCfg = config::parseConfigFile(filepath);
|
||||
if (!pbCfg.has_value()) {
|
||||
return false;
|
||||
}
|
||||
// process the rest of the config file data and configure the CAN buses.
|
||||
if (!processPbCfg(*pbCfg)) {
|
||||
return false;
|
||||
}
|
||||
LOG(INFO) << "CAN HAL has been configured!";
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" int main(int argc, char* argv[]) {
|
||||
std::string configFilepath = static_cast<std::string>(kDefaultConfigPath);
|
||||
|
||||
// allow for CLI specification of a config file.
|
||||
if (argc == 2) {
|
||||
configFilepath = argv[1];
|
||||
} else if (argc > 2) {
|
||||
std::cerr << "usage: " << argv[0] << " [optional config filepath]";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!configuratorStart(configFilepath)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace android::hardware::automotive::can
|
||||
200
automotive/can/aidl/default/tools/configurator/canprototools.cpp
Normal file
200
automotive/can/aidl/default/tools/configurator/canprototools.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 "canprototools.h"
|
||||
|
||||
#include <aidl/android/hardware/automotive/can/IndexedInterface.h>
|
||||
#include <aidl/android/hardware/automotive/can/NativeInterface.h>
|
||||
#include <aidl/android/hardware/automotive/can/SlcanInterface.h>
|
||||
#include <aidl/android/hardware/automotive/can/VirtualInterface.h>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/text_format.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace android::hardware::automotive::can::config {
|
||||
|
||||
using ::aidl::android::hardware::automotive::can::BusConfig;
|
||||
using ::aidl::android::hardware::automotive::can::IndexedInterface;
|
||||
using ::aidl::android::hardware::automotive::can::InterfaceType;
|
||||
using ::aidl::android::hardware::automotive::can::NativeInterface;
|
||||
using ::aidl::android::hardware::automotive::can::Result;
|
||||
using ::aidl::android::hardware::automotive::can::SlcanInterface;
|
||||
using ::aidl::android::hardware::automotive::can::VirtualInterface;
|
||||
|
||||
/**
|
||||
* Helper function for parseConfigFile. readString is used to get the fist n characters (n) from an
|
||||
* istream object (s) and return it as a string object.
|
||||
*
|
||||
* \param s istream of the file you intend to read.
|
||||
* \param n streamsize object of the number of characters you'd like.
|
||||
* \return optional string containing up to n characters from the stream(s) you provided.
|
||||
*/
|
||||
static std::optional<std::string> readString(std::istream& s, std::streamsize n) {
|
||||
char buff[n];
|
||||
auto got = s.read(buff, n).gcount();
|
||||
if (!s.good() && !s.eof()) return std::nullopt;
|
||||
return std::string(buff, 0, std::min(n, got));
|
||||
}
|
||||
|
||||
std::optional<CanBusConfig> parseConfigFile(const std::string& filepath) {
|
||||
std::ifstream cfg_stream(filepath);
|
||||
|
||||
// text headers that would be present in a plaintext proto config file.
|
||||
static const std::array<std::string, 3> text_headers = {"buses", "#", "controller"};
|
||||
auto cfg_file_snippet = readString(cfg_stream, 10);
|
||||
|
||||
if (!cfg_file_snippet.has_value()) {
|
||||
LOG(ERROR) << "Can't open " << filepath << " for reading";
|
||||
return std::nullopt;
|
||||
}
|
||||
cfg_stream.seekg(0);
|
||||
|
||||
// check if any of the textHeaders are at the start of the config file.
|
||||
bool text_format = false;
|
||||
for (auto const& header : text_headers) {
|
||||
if (cfg_file_snippet->compare(0, header.length(), header) == 0) {
|
||||
text_format = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CanBusConfig config;
|
||||
if (text_format) {
|
||||
google::protobuf::io::IstreamInputStream pb_stream(&cfg_stream);
|
||||
if (!google::protobuf::TextFormat::Parse(&pb_stream, &config)) {
|
||||
LOG(ERROR) << "Failed to parse (text format) " << filepath;
|
||||
return std::nullopt;
|
||||
}
|
||||
} else if (!config.ParseFromIstream(&cfg_stream)) {
|
||||
LOG(ERROR) << "Failed to parse (binary format) " << filepath;
|
||||
return std::nullopt;
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
std::optional<BusConfig> fromPbBus(const Bus& pb_bus) {
|
||||
BusConfig bus_cfg = {};
|
||||
bus_cfg.name = pb_bus.name();
|
||||
|
||||
switch (pb_bus.iface_type_case()) {
|
||||
case Bus::kNative: {
|
||||
const std::string ifname = pb_bus.native().ifname();
|
||||
const std::vector<std::string> serials = {pb_bus.native().serialno().begin(),
|
||||
pb_bus.native().serialno().end()};
|
||||
if (ifname.empty() == serials.empty()) {
|
||||
LOG(ERROR) << "Invalid config: native type bus must have an iface name xor a "
|
||||
<< "serial number";
|
||||
return std::nullopt;
|
||||
}
|
||||
bus_cfg.bitrate = pb_bus.bitrate();
|
||||
NativeInterface nativeif = {};
|
||||
if (!ifname.empty())
|
||||
nativeif.interfaceId.set<NativeInterface::InterfaceId::Tag::ifname>(ifname);
|
||||
if (!serials.empty())
|
||||
nativeif.interfaceId.set<NativeInterface::InterfaceId::Tag::serialno>(serials);
|
||||
bus_cfg.interfaceId.set<BusConfig::InterfaceId::Tag::nativeif>(nativeif);
|
||||
break;
|
||||
}
|
||||
case Bus::kSlcan: {
|
||||
const std::string ttyname = pb_bus.slcan().ttyname();
|
||||
const std::vector<std::string> serials = {pb_bus.slcan().serialno().begin(),
|
||||
pb_bus.slcan().serialno().end()};
|
||||
if (ttyname.empty() == serials.empty()) {
|
||||
LOG(ERROR) << "Invalid config: slcan type bus must have a tty name xor a serial "
|
||||
<< "number";
|
||||
return std::nullopt;
|
||||
}
|
||||
bus_cfg.bitrate = pb_bus.bitrate();
|
||||
SlcanInterface slcan = {};
|
||||
if (!ttyname.empty())
|
||||
slcan.interfaceId.set<SlcanInterface::InterfaceId::Tag::ttyname>(ttyname);
|
||||
if (!serials.empty())
|
||||
slcan.interfaceId.set<SlcanInterface::InterfaceId::Tag::serialno>(serials);
|
||||
bus_cfg.interfaceId.set<BusConfig::InterfaceId::Tag::slcan>(slcan);
|
||||
break;
|
||||
}
|
||||
case Bus::kVirtual: {
|
||||
// Theoretically, we could just create the next available vcan iface.
|
||||
const std::string ifname = pb_bus.virtual_().ifname();
|
||||
if (ifname.empty()) {
|
||||
LOG(ERROR) << "Invalid config: native type bus must have an iface name";
|
||||
return std::nullopt;
|
||||
}
|
||||
VirtualInterface virtualif = {};
|
||||
virtualif.ifname = ifname;
|
||||
bus_cfg.interfaceId.set<BusConfig::InterfaceId::Tag::virtualif>(virtualif);
|
||||
break;
|
||||
}
|
||||
case Bus::kIndexed: {
|
||||
const uint8_t index = pb_bus.indexed().index();
|
||||
if (index > UINT8_MAX) {
|
||||
LOG(ERROR) << "Interface index out of range: " << index;
|
||||
return std::nullopt;
|
||||
}
|
||||
IndexedInterface indexedif = {};
|
||||
indexedif.index = index;
|
||||
bus_cfg.interfaceId.set<BusConfig::InterfaceId::Tag::indexed>(indexedif);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG(ERROR) << "Invalid config: bad interface type for " << bus_cfg.name;
|
||||
return std::nullopt;
|
||||
}
|
||||
return bus_cfg;
|
||||
}
|
||||
|
||||
std::optional<InterfaceType> getHalIftype(const Bus& pb_bus) {
|
||||
switch (pb_bus.iface_type_case()) {
|
||||
case Bus::kNative:
|
||||
return InterfaceType::NATIVE;
|
||||
case Bus::kSlcan:
|
||||
return InterfaceType::SLCAN;
|
||||
case Bus::kVirtual:
|
||||
return InterfaceType::VIRTUAL;
|
||||
case Bus::kIndexed:
|
||||
return InterfaceType::INDEXED;
|
||||
default:
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::string resultStringFromStatus(const ndk::ScopedAStatus& status) {
|
||||
const auto res = static_cast<Result>(status.getServiceSpecificError());
|
||||
switch (res) {
|
||||
case Result::OK:
|
||||
return "OK";
|
||||
case Result::UNKNOWN_ERROR:
|
||||
return "UNKNOWN_ERROR";
|
||||
case Result::INVALID_STATE:
|
||||
return "INVALID_STATE";
|
||||
case Result::NOT_SUPPORTED:
|
||||
return "NOT_SUPPORTED";
|
||||
case Result::BAD_INTERFACE_ID:
|
||||
return "BAD_INTERFACE_ID";
|
||||
case Result::BAD_BITRATE:
|
||||
return "BAD_BITRATE";
|
||||
case Result::BAD_BUS_NAME:
|
||||
return "BAD_BUS_NAME";
|
||||
case Result::INTERFACE_DOWN:
|
||||
return "INTERFACE_DOWN";
|
||||
default:
|
||||
return "Invalid Result!";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android::hardware::automotive::can::config
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "canbus_config.pb.h"
|
||||
|
||||
#include <aidl/android/hardware/automotive/can/BusConfig.h>
|
||||
#include <aidl/android/hardware/automotive/can/InterfaceType.h>
|
||||
#include <aidl/android/hardware/automotive/can/Result.h>
|
||||
|
||||
namespace android::hardware::automotive::can::config {
|
||||
|
||||
/**
|
||||
* This reads the protobuf config file into a protobuf object. Both text based protobuf files as
|
||||
* well as binary format protobuf files are supported.
|
||||
*
|
||||
* \param filepath string containing the name of the config file to read.
|
||||
* \return a CanBusConfig protobuf object constructed from the config file.
|
||||
*/
|
||||
std::optional<CanBusConfig> parseConfigFile(const std::string& filepath);
|
||||
|
||||
/**
|
||||
* Converts protobuf format single-bus config object to a HAL bus config object.
|
||||
*
|
||||
* \param pb_bus is the protobuf object representing a the configuration of one CAN bus.
|
||||
* \return a converted HAL bus config object.
|
||||
*/
|
||||
std::optional<::aidl::android::hardware::automotive::can::BusConfig> fromPbBus(const Bus& pb_bus);
|
||||
|
||||
/**
|
||||
* Get the CAN HAL interface type specified by a given protobuf config object.
|
||||
*
|
||||
* \param pb_bus is the protobuf object representing a the configuration of one CAN bus.
|
||||
* \return the CAN HAL interface type.
|
||||
*/
|
||||
std::optional<::aidl::android::hardware::automotive::can::InterfaceType> getHalIftype(
|
||||
const Bus& pb_bus);
|
||||
|
||||
std::string resultStringFromStatus(const ndk::ScopedAStatus& status);
|
||||
|
||||
} // namespace android::hardware::automotive::can::config
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// Copyright (C) 2022 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.
|
||||
//
|
||||
|
||||
package {
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "android.hardware.automotive.can-aidl-config-format",
|
||||
defaults: ["android.hardware.automotive.can@defaults"],
|
||||
proto: {
|
||||
export_proto_headers: true,
|
||||
type: "full",
|
||||
},
|
||||
strip: {
|
||||
keep_symbols: true,
|
||||
},
|
||||
srcs: ["canbus_config.proto"],
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package android.hardware.automotive.can.config;
|
||||
|
||||
message IfaceNative {
|
||||
string ifname = 1;
|
||||
repeated string serialno = 2;
|
||||
};
|
||||
|
||||
message IfaceSlcan {
|
||||
string ttyname = 1;
|
||||
repeated string serialno = 2;
|
||||
};
|
||||
|
||||
message IfaceVirtual {
|
||||
string ifname = 1;
|
||||
};
|
||||
|
||||
message IfaceIndexed {
|
||||
uint32 index = 1;
|
||||
};
|
||||
|
||||
message Bus {
|
||||
string name = 1; // this is the name presented in the HAL
|
||||
oneof iface_type {
|
||||
IfaceNative native = 2;
|
||||
IfaceSlcan slcan = 3;
|
||||
IfaceVirtual virtual = 4;
|
||||
IfaceIndexed indexed = 5;
|
||||
}
|
||||
uint32 bitrate = 6;
|
||||
};
|
||||
|
||||
message CanBusConfig {
|
||||
repeated Bus buses = 1;
|
||||
};
|
||||
51
automotive/can/aidl/vts/functional/Android.bp
Normal file
51
automotive/can/aidl/vts/functional/Android.bp
Normal file
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// Copyright (C) 2022 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.
|
||||
//
|
||||
|
||||
package {
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "VtsHalCanControllerV1_0Test",
|
||||
defaults: [
|
||||
"VtsHalTargetTestDefaults",
|
||||
"android.hardware.automotive.can@defaults",
|
||||
"use_libaidlvintf_gtest_helper_static",
|
||||
],
|
||||
cpp_std: "experimental",
|
||||
srcs: [
|
||||
"CanControllerAidlTest.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
],
|
||||
static_libs: [
|
||||
"android.hardware.automotive.can-V1-ndk",
|
||||
"android.hardware.automotive.can@libnetdevice",
|
||||
"libnl++",
|
||||
"libgmock",
|
||||
],
|
||||
test_suites: [
|
||||
"general-tests",
|
||||
"vts",
|
||||
],
|
||||
}
|
||||
96
automotive/can/aidl/vts/functional/CanControllerAidlTest.cpp
Normal file
96
automotive/can/aidl/vts/functional/CanControllerAidlTest.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 <aidl/Gtest.h>
|
||||
#include <aidl/Vintf.h>
|
||||
#include <aidl/android/hardware/automotive/can/BusConfig.h>
|
||||
#include <aidl/android/hardware/automotive/can/ICanController.h>
|
||||
#include <aidl/android/hardware/automotive/can/Result.h>
|
||||
#include <aidl/android/hardware/automotive/can/VirtualInterface.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <libnetdevice/libnetdevice.h>
|
||||
#include <libnl++/MessageFactory.h>
|
||||
#include <libnl++/Socket.h>
|
||||
#include <libnl++/printer.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
using aidl::android::hardware::automotive::can::BusConfig;
|
||||
using aidl::android::hardware::automotive::can::ICanController;
|
||||
using aidl::android::hardware::automotive::can::VirtualInterface;
|
||||
using namespace std::chrono_literals;
|
||||
using namespace std::string_literals;
|
||||
|
||||
class CanControllerAidlTest : public ::testing::TestWithParam<std::string> {
|
||||
public:
|
||||
virtual void SetUp() override {
|
||||
android::base::SetDefaultTag("CAN_HAL_VTS");
|
||||
android::base::SetMinimumLogSeverity(android::base::VERBOSE);
|
||||
const auto instance = ICanController::descriptor + "/default"s;
|
||||
mCanControllerService = ICanController::fromBinder(
|
||||
ndk::SpAIBinder(AServiceManager_waitForService(instance.c_str())));
|
||||
|
||||
ASSERT_NE(mCanControllerService, nullptr);
|
||||
}
|
||||
virtual void TearDown() override {}
|
||||
|
||||
static bool mTestCaseInitialized;
|
||||
std::shared_ptr<ICanController> mCanControllerService;
|
||||
};
|
||||
|
||||
// we can't test a real bus, since we can't make any assumptions about hardware
|
||||
// this checks upBus, getInterfaceName, and downBus
|
||||
TEST_P(CanControllerAidlTest, ToggleBus) {
|
||||
const std::string_view canIface = "vcan50";
|
||||
const std::string busName = "VTS_CAN";
|
||||
|
||||
std::string upBusReturn; // should be vcan50
|
||||
BusConfig config = {};
|
||||
VirtualInterface iface = {};
|
||||
iface.ifname = canIface;
|
||||
config.interfaceId.set<BusConfig::InterfaceId::Tag::virtualif>(iface);
|
||||
config.name = busName;
|
||||
auto aidlStatus = mCanControllerService->upBus(config, &upBusReturn);
|
||||
ASSERT_TRUE(aidlStatus.isOk());
|
||||
EXPECT_EQ(upBusReturn, canIface);
|
||||
|
||||
std::string ifaceName;
|
||||
aidlStatus = mCanControllerService->getInterfaceName(busName, &ifaceName);
|
||||
ASSERT_TRUE(aidlStatus.isOk());
|
||||
EXPECT_EQ(ifaceName, canIface);
|
||||
|
||||
aidlStatus = mCanControllerService->downBus(busName);
|
||||
ASSERT_TRUE(aidlStatus.isOk());
|
||||
}
|
||||
|
||||
TEST_P(CanControllerAidlTest, GetSupported) {
|
||||
LOG(VERBOSE) << "Get the supported iface types";
|
||||
std::vector<::aidl::android::hardware::automotive::can::InterfaceType> supportedTypes;
|
||||
auto aidlStatus = mCanControllerService->getSupportedInterfaceTypes(&supportedTypes);
|
||||
ASSERT_TRUE(aidlStatus.isOk());
|
||||
EXPECT_FALSE(supportedTypes.empty());
|
||||
}
|
||||
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CanControllerAidlTest);
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
PerInstance, CanControllerAidlTest,
|
||||
testing::ValuesIn(android::getAidlHalInstanceNames(ICanController::descriptor)),
|
||||
android::PrintInstanceNameToString);
|
||||
3
automotive/can/aidl/vts/functional/OWNERS
Normal file
3
automotive/can/aidl/vts/functional/OWNERS
Normal file
@@ -0,0 +1,3 @@
|
||||
# Bug component: 533426
|
||||
twasilczyk@google.com
|
||||
chrisweir@google.com
|
||||
@@ -68,6 +68,14 @@
|
||||
<instance>default</instance>
|
||||
</interface>
|
||||
</hal>
|
||||
<hal format="aidl" optional="true">
|
||||
<name>android.hardware.automotive.can</name>
|
||||
<version>1</version>
|
||||
<interface>
|
||||
<name>ICanController</name>
|
||||
<instance>default</instance>
|
||||
</interface>
|
||||
</hal>
|
||||
<hal format="hidl" optional="true">
|
||||
<name>android.hardware.automotive.can</name>
|
||||
<version>1.0</version>
|
||||
|
||||
Reference in New Issue
Block a user