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