1 /*
2 * Copyright (C) 2020 Google Inc. All Rights Reserved.
3 */
4
5 #include "ExtraCanClient.h"
6
7 #include <VehicleUtils.h>
8 #include <VehicleHalTypes.h>
9
10 #include <aidl/android/hardware/automotive/vehicle/VehicleDisplay.h>
11 #include <aidl/android/hardware/automotive/vehicle/VehicleHwKeyInputAction.h>
12 #include <android-base/logging.h>
13 #include <android/keycodes.h>
14 #include <libprotocan/MessageDef.h>
15
16 #include <cmath>
17 #include <set>
18
19 namespace android::hardware::automotive::vehicle::V2_0::impl {
20
21 using can::V1_0::CanMessage;
22 using can::V1_0::CanMessageId;
23 using can::V1_0::ICanBus;
24 using protocan::MessageDef;
25 using protocan::Signal;
26 using ::aidl::android::hardware::automotive::vehicle::VehicleArea;
27 using ::aidl::android::hardware::automotive::vehicle::VehicleDisplay;
28 using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction;
29 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
30 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
31
32 namespace can {
33 // clang-format off
34
35 static const MessageDef EncEvent(0x18A, 5, {
36 {"EncPos", Signal(0, 16)},
37 {"EncDir", Signal(16, 2)},
38 {"Buttons", Signal(24, 16)},
39 });
40
41 static const MessageDef ModuleControl(0x000, 2, {
42 {"ReqState", Signal(0, 8)},
43 {"Address", Signal(8, 8)},
44 });
45
46 // clang-format on
47 } // namespace can
48
ExtraCanClient()49 ExtraCanClient::ExtraCanClient() : CanClient("aae") {}
50
onReady(const sp<ICanBus> & canBus)51 void ExtraCanClient::onReady(const sp<ICanBus>& canBus) {
52 auto msg = can::ModuleControl.makeDefault();
53 can::ModuleControl["ReqState"].set(msg, 1);
54 canBus->send(msg);
55 }
56
appendKeyInput(std::vector<VehiclePropValue> & props,int32_t keyCode,bool keyDown)57 void ExtraCanClient::appendKeyInput(std::vector<VehiclePropValue>& props, int32_t keyCode, bool keyDown) {
58 VehiclePropValue prop = {};
59
60 prop.areaId = toInt(VehicleArea::GLOBAL);
61 prop.prop = toInt(VehicleProperty::HW_KEY_INPUT);
62 prop.status = VehiclePropertyStatus::AVAILABLE;
63 prop.value.int32Values = {
64 toInt(keyDown ? VehicleHwKeyInputAction::ACTION_DOWN
65 : VehicleHwKeyInputAction::ACTION_UP),
66 keyCode,
67 toInt(VehicleDisplay::MAIN),
68 };
69
70 props.push_back(prop);
71 }
72
appendRepeatedKeyInput(std::vector<VehiclePropValue> & props,int32_t keyCode,unsigned repeat)73 void ExtraCanClient::appendRepeatedKeyInput(std::vector<VehiclePropValue>& props, int32_t keyCode,
74 unsigned repeat) {
75 for (unsigned i = 0; i < repeat; i++) {
76 appendKeyInput(props, keyCode, true);
77 appendKeyInput(props, keyCode, false);
78 }
79 }
80
decodeButtons(uint16_t val)81 std::set<int> decodeButtons(uint16_t val) {
82 std::set<int> buttons;
83
84 if (val & (1 << 0)) buttons.insert(AKEYCODE_BUTTON_A); // NAV
85 if (val & (1 << 1)) buttons.insert(AKEYCODE_BUTTON_B); // TEL
86 if (val & (1 << 2)) buttons.insert(AKEYCODE_MUSIC); // MEDIA
87 if (val & (1 << 3)) buttons.insert(AKEYCODE_MENU); // MENU
88 if (val & (1 << 4)) buttons.insert(AKEYCODE_BACK); // BACK
89 if (val & (1 << 5)) buttons.insert(AKEYCODE_ENTER); // ENC-PUSH
90 if (val & (1 << 8)) buttons.insert(AKEYCODE_DPAD_UP); // DPAD-UP
91 if (val & (1 << 9)) buttons.insert(AKEYCODE_DPAD_DOWN); // DPAD-DOWN
92 if (val & (1 << 10)) buttons.insert(AKEYCODE_DPAD_LEFT); // DPAD-LEFT
93 if (val & (1 << 11)) buttons.insert(AKEYCODE_DPAD_RIGHT); // DPAD-RIGHT
94
95 return buttons;
96 }
97
onReceive(const CanMessage & message)98 ::android::hardware::Return<void> ExtraCanClient::onReceive(const CanMessage& message) {
99 std::vector<VehiclePropValue> props;
100
101 if (message.id == can::EncEvent.id) {
102 if (!can::EncEvent.validate(message)) return {};
103 LOG(INFO) << "EncPos: " << can::EncEvent["EncPos"].get(message);
104 LOG(INFO) << "EncDir: " << can::EncEvent["EncDir"].get(message);
105 LOG(INFO) << "Buttons: " << can::EncEvent["Buttons"].get(message);
106
107 uint16_t encPos = can::EncEvent["EncPos"].get(message);
108 static std::optional<uint16_t> prevEncPos;
109 if (prevEncPos.has_value()) {
110 int16_t diff = encPos - *prevEncPos;
111 if (diff > 0) {
112 appendRepeatedKeyInput(props, AKEYCODE_DPAD_DOWN, diff);
113 } else if (diff < 0) {
114 appendRepeatedKeyInput(props, AKEYCODE_DPAD_UP, -diff);
115 }
116 }
117 prevEncPos = encPos;
118
119 static std::set<int> oldButtons;
120 auto newButtons = decodeButtons(can::EncEvent["Buttons"].get(message));
121 for (int key : newButtons) {
122 if (oldButtons.count(key) == 0) {
123 appendKeyInput(props, key, true);
124 }
125 }
126 for (int key : oldButtons) {
127 if (newButtons.count(key) == 0) {
128 appendKeyInput(props, key, false);
129 }
130 }
131 oldButtons = newButtons;
132 }
133
134 updateTimestamps(props, message.timestamp);
135 sendPropertyEvent(props);
136 return {};
137 }
138
139 } // namespace aidl::android::hardware::automotive::vehicle
140