blob: 3b63fe404b65192876ad6d5735f6b53a477f7dfb [file] [log] [blame]
Tomasz Wasilczyk87329672019-07-12 11:43:00 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "CanController.h"
18
19#include "CanBusNative.h"
20#include "CanBusVirtual.h"
21
22#include <android-base/logging.h>
23#include <android/hidl/manager/1.2/IServiceManager.h>
24
25#include <regex>
26
27namespace android {
28namespace hardware {
29namespace automotive {
30namespace can {
31namespace V1_0 {
32namespace implementation {
33
34using IfaceIdDisc = ICanController::BusConfiguration::InterfaceIdentifier::hidl_discriminator;
35
36Return<void> CanController::getSupportedInterfaceTypes(getSupportedInterfaceTypes_cb _hidl_cb) {
37 _hidl_cb({
38 ICanController::InterfaceType::VIRTUAL,
39 ICanController::InterfaceType::SOCKETCAN,
40 });
41 return {};
42}
43
44static bool isValidName(const std::string& name) {
45 static const std::regex nameRE("^[a-zA-Z0-9_]{1,32}$");
46 return std::regex_match(name, nameRE);
47}
48
49Return<ICanController::Result> CanController::upInterface(
50 const ICanController::BusConfiguration& config) {
51 LOG(VERBOSE) << "Attempting to bring interface up: " << toString(config);
52
53 std::lock_guard<std::mutex> lck(mCanBusesGuard);
54
55 if (!isValidName(config.name)) {
56 LOG(ERROR) << "Bus name " << config.name << " is invalid";
57 return ICanController::Result::UNKNOWN_ERROR;
58 }
59
60 if (mCanBuses.find(config.name) != mCanBuses.end()) {
61 LOG(ERROR) << "Bus " << config.name << " is already up";
62 return ICanController::Result::INVALID_STATE;
63 }
64
65 sp<CanBus> busService;
66
67 if (config.iftype == ICanController::InterfaceType::SOCKETCAN) {
68 // TODO(b/135918744): support serialno
69 if (config.interfaceId.getDiscriminator() == IfaceIdDisc::address) {
70 busService = new CanBusNative(config.interfaceId.address(), config.baudrate);
71 } else {
72 return ICanController::Result::BAD_ADDRESS;
73 }
74 } else if (config.iftype == ICanController::InterfaceType::VIRTUAL) {
75 if (config.interfaceId.getDiscriminator() == IfaceIdDisc::address) {
76 busService = new CanBusVirtual(config.interfaceId.address());
77 } else {
78 return ICanController::Result::BAD_ADDRESS;
79 }
80 } else {
81 return ICanController::Result::NOT_SUPPORTED;
82 }
83
Tomasz Wasilczyka9061962019-11-04 12:53:09 -080084 busService->setErrorCallback([this, name = config.name]() { downInterface(name); });
85
Tomasz Wasilczyk87329672019-07-12 11:43:00 -070086 const auto result = busService->up();
87 if (result != ICanController::Result::OK) return result;
88
89 if (busService->registerAsService(config.name) != OK) {
90 LOG(ERROR) << "Failed to register ICanBus/" << config.name;
91 if (!busService->down()) {
92 LOG(WARNING) << "Failed to bring down CAN bus that failed to register";
93 }
94 return ICanController::Result::UNKNOWN_ERROR;
95 }
96
97 mCanBuses[config.name] = busService;
98
99 return ICanController::Result::OK;
100}
101
Tomasz Wasilczyka9061962019-11-04 12:53:09 -0800102static bool unregisterCanBusService(const hidl_string& name, sp<CanBus> busService) {
103 auto manager = hidl::manager::V1_2::IServiceManager::getService();
104 if (!manager) return false;
105 const auto res = manager->tryUnregister(ICanBus::descriptor, name, busService);
106 if (!res.isOk()) return false;
107 return res;
108}
109
Tomasz Wasilczyk87329672019-07-12 11:43:00 -0700110Return<bool> CanController::downInterface(const hidl_string& name) {
111 LOG(VERBOSE) << "Attempting to bring interface down: " << name;
112
113 std::lock_guard<std::mutex> lck(mCanBusesGuard);
114
115 auto busEntry = mCanBuses.extract(name);
116 if (!busEntry) {
117 LOG(WARNING) << "Interface " << name << " is not up";
118 return false;
119 }
120
121 auto success = true;
122
Tomasz Wasilczyka9061962019-11-04 12:53:09 -0800123 if (!unregisterCanBusService(name, busEntry.mapped())) {
Tomasz Wasilczyk87329672019-07-12 11:43:00 -0700124 LOG(ERROR) << "Couldn't unregister " << name;
125 // don't return yet, let's try to do best-effort cleanup
126 success = false;
127 }
128
129 if (!busEntry.mapped()->down()) {
130 LOG(ERROR) << "Couldn't bring " << name << " down";
131 success = false;
132 }
133
134 return success;
135}
136
137} // namespace implementation
138} // namespace V1_0
139} // namespace can
140} // namespace automotive
141} // namespace hardware
142} // namespace android