blob: 616a5a64c18c9c90bf028a2fe804c39fc619ecc7 [file] [log] [blame]
James Bootsma9eb78a32017-06-13 09:42:00 -06001/*
2 *Copyright (c) 2017, The Linux Foundation. All rights reserved.
3 *
4 *
5 *Redistribution and use in source and binary forms, with or without
6 *modification, are permitted provided that the following conditions are
7 *met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following
12 * disclaimer in the documentation and/or other materials provided
13 * with the distribution.
14 * * Neither the name of The Linux Foundation nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 *
19 *THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
20 *WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
22 *ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
23 *BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26 *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 *WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28 *OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29 *IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32
33#include <iostream> // std::cin, std::cout
34#include <queue> // std::queue
35#include <mutex> // std::mutex, std::unique_lock
36#include <condition_variable> // std::condition_variable
37#include <cstdlib>
38#include <thread>
39
40#include <hwbinder/ProcessState.h>
41
42#include <com/qualcomm/qti/ant/1.0/IAntHci.h>
43#include <com/qualcomm/qti/ant/1.0/IAntHciCallbacks.h>
44#include <com/qualcomm/qti/ant/1.0/types.h>
45
46#include <utils/Log.h>
47
48
49#include <hidl/Status.h>
50#include <hwbinder/ProcessState.h>
51#include "ant_types.h"
52#include "AntHidlClient.h"
53
54using com::qualcomm::qti::ant::V1_0::IAntHci;
55using com::qualcomm::qti::ant::V1_0::IAntHciCallbacks;
56using com::qualcomm::qti::ant::V1_0::AntPacket;
57using com::qualcomm::qti::ant::V1_0::Status;
58
59using ::android::hardware::hidl_vec;
60
61
62using android::hardware::ProcessState;
63using ::android::hardware::Return;
64using ::android::hardware::Void;
65using ::android::sp;
66android::sp<IAntHci> anthci;
67typedef std::unique_lock<std::mutex> Lock;
68
James Bootsmac3378cc2017-09-19 17:10:11 -060069#define POLL_TIMEOUT_MS 100
James Bootsma9eb78a32017-06-13 09:42:00 -060070
71struct ant_hci_t {
72public:
73 std::condition_variable rx_cond;
74 std::condition_variable on_cond;
James Bootsmac3378cc2017-09-19 17:10:11 -060075 std::condition_variable data_cond;
James Bootsma9eb78a32017-06-13 09:42:00 -060076 std::mutex on_mtx;
77 std::mutex rx_mtx;
James Bootsmac3378cc2017-09-19 17:10:11 -060078 std::mutex data_mtx;
James Bootsma9eb78a32017-06-13 09:42:00 -060079 ant_power_state_t state;
James Bootsmac3378cc2017-09-19 17:10:11 -060080 volatile bool rx_processing;
James Bootsma9eb78a32017-06-13 09:42:00 -060081};
82
83static struct ant_hci_t ant_hci;
84
85Return<void> initialization_complete(bool is_hci_initialize)
86{
James Bootsmac3378cc2017-09-19 17:10:11 -060087 ALOGI("%s start ", __func__ );
James Bootsma9eb78a32017-06-13 09:42:00 -060088
89 Lock lk(ant_hci.on_mtx);
90 if (is_hci_initialize)
91 {
92 ant_hci.state = ANT_RADIO_ENABLED;
James Bootsma9eb78a32017-06-13 09:42:00 -060093 }
94 else
95 {
96 ALOGE("%s:Ant hci init failed :%d", __func__, is_hci_initialize);
97 ant_hci.state = ANT_RADIO_DISABLED;
98 }
99 ant_hci.on_cond.notify_all();
100 ALOGI("%s: exit", __func__);
101 return Void();
102}
103
104
105class AntHciCallbacks : public IAntHciCallbacks {
106public:
107 AntHciCallbacks() {};
108 virtual ~AntHciCallbacks() = default;
109
110 Return<void> initializationComplete(Status status)
111 {
112 ALOGI("%s", __func__);
113 if(status == Status::SUCCESS)
114 {
115 initialization_complete(true);
116 } else {
117 initialization_complete(false);
118 }
119 ALOGI("%s: exit", __func__);
120 return Void();
121 }
122
123 Return<void> antControlReceived(const hidl_vec<uint8_t>& event)
124 {
James Bootsmac3378cc2017-09-19 17:10:11 -0600125 ALOGV("%s:start ", __func__);
James Bootsma9eb78a32017-06-13 09:42:00 -0600126 // Make sure we don't overwrite a message still processing.
James Bootsmac3378cc2017-09-19 17:10:11 -0600127 Lock lk(ant_hci.rx_mtx);
128 if(ant_hci.rx_processing && ant_hci.state == ANT_RADIO_ENABLED)
James Bootsma9eb78a32017-06-13 09:42:00 -0600129 {
130 ant_hci.rx_cond.wait(lk);
131 }
James Bootsma9eb78a32017-06-13 09:42:00 -0600132
133 memcpy(&aucRxBuffer[0][0], event.data(), event.size());
134 iRxBufferLength[0] = event.size();
James Bootsmac3378cc2017-09-19 17:10:11 -0600135 std::unique_lock< std::mutex> lock(ant_hci.data_mtx);
136 ALOGD("%s: notify data avail", __func__);
James Bootsmafbdd6d82017-10-05 09:01:41 -0600137 ant_hci.rx_processing = true;
James Bootsmac3378cc2017-09-19 17:10:11 -0600138 ant_hci.data_cond.notify_all();
139 ALOGV("%s: End", __func__);
James Bootsma9eb78a32017-06-13 09:42:00 -0600140 return Void();
141 }
142
143 Return<void> antDataReceived(const hidl_vec<uint8_t>& event)
144 {
James Bootsmac3378cc2017-09-19 17:10:11 -0600145 ALOGV("%s:start ", __func__);
James Bootsma9eb78a32017-06-13 09:42:00 -0600146 // Make sure we don't overwrite a message still processing.
James Bootsmac3378cc2017-09-19 17:10:11 -0600147 Lock lk(ant_hci.rx_mtx);
148 if(ant_hci.rx_processing && ant_hci.state == ANT_RADIO_ENABLED)
James Bootsma9eb78a32017-06-13 09:42:00 -0600149 {
150 ant_hci.rx_cond.wait(lk);
151 }
James Bootsma9eb78a32017-06-13 09:42:00 -0600152
153 memcpy(&aucRxBuffer[0][0], event.data(), event.size());
154 iRxBufferLength[0] = event.size();
James Bootsmac3378cc2017-09-19 17:10:11 -0600155 std::unique_lock< std::mutex> lock(ant_hci.data_mtx);
156 ALOGD("%s: notify data avail", __func__);
James Bootsmafbdd6d82017-10-05 09:01:41 -0600157 ant_hci.rx_processing = true;
James Bootsmac3378cc2017-09-19 17:10:11 -0600158 ant_hci.data_cond.notify_all();
159 ALOGV("%s: exit", __func__);
James Bootsma9eb78a32017-06-13 09:42:00 -0600160 return Void();
161 }
162};
163
164bool hci_initialize()
165{
166 ALOGI("%s", __func__);
167
168 anthci = IAntHci::getService();
169
170 if(anthci != nullptr)
171 {
172 ant_hci.state = ANT_RADIO_ENABLING;
173 ant_hci.rx_processing = false;
174 android::sp<IAntHciCallbacks> callbacks = new AntHciCallbacks();
175 anthci->initialize(callbacks);
James Bootsmac3378cc2017-09-19 17:10:11 -0600176 ALOGV("%s: exit", __func__);
James Bootsma9eb78a32017-06-13 09:42:00 -0600177 return true;
178 } else {
179 return false;
180 }
181}
182
183void hci_close() {
184 ALOGV("%s", __func__);
185
186 if(anthci != nullptr)
187 {
James Bootsmac3378cc2017-09-19 17:10:11 -0600188 std::unique_lock< std::mutex> lock(ant_hci.data_mtx);
189 ant_hci.data_cond.notify_all();
James Bootsmaf17bf962018-01-03 16:58:15 -0700190 auto hidl_daemon_status = anthci->close();
191 if(!hidl_daemon_status.isOk())
192 {
193 ALOGE("%s: HIDL daemon is dead", __func__);
194 }
James Bootsma9eb78a32017-06-13 09:42:00 -0600195 }
James Bootsmac3378cc2017-09-19 17:10:11 -0600196 ant_hci.state = ANT_RADIO_DISABLED;
James Bootsma9eb78a32017-06-13 09:42:00 -0600197 ant_rx_clear();
198 anthci =nullptr;
James Bootsma9eb78a32017-06-13 09:42:00 -0600199 ALOGI("%s: exit", __func__);
200}
201
202ANT_UINT ant_get_status()
203{
204 return ant_hci.state;
205}
206
207ANTStatus ant_tx_write(ANT_U8 *pucTxMessage,ANT_U8 ucMessageLength)
208{
209 AntPacket data;
210 ANT_U8 packet_type;
211 ALOGI("%s: start", __func__);
212 packet_type = *pucTxMessage;
213 ALOGV("%s: proto type :%d", __func__, packet_type);
214 if (anthci != nullptr)
215 {
James Bootsma7b86e792017-08-10 11:38:40 -0600216 data.setToExternal(pucTxMessage+1, ucMessageLength-1);
James Bootsma9eb78a32017-06-13 09:42:00 -0600217 if (packet_type == ANT_DATA_TYPE_PACKET)
218 {
James Bootsmaa890bca2017-12-14 13:55:11 -0700219 auto hidl_daemon_status = anthci->sendAntData(data);
James Bootsmaf17bf962018-01-03 16:58:15 -0700220 if (!hidl_daemon_status.isOk())
221 {
222 ALOGE("%s:sendAntData failed,HIDL dead", __func__);
223 return -1;
224 }
James Bootsma9eb78a32017-06-13 09:42:00 -0600225 } else {
James Bootsmaa890bca2017-12-14 13:55:11 -0700226 auto hidl_daemon_status = anthci->sendAntControl(data);
James Bootsmaf17bf962018-01-03 16:58:15 -0700227 if (!hidl_daemon_status.isOk())
228 {
229 ALOGE("%s:sendAntControl failed,HIDL dead", __func__);
230 return -1;
231 }
James Bootsma9eb78a32017-06-13 09:42:00 -0600232 }
233 } else {
234 ALOGE("%s: antHci is NULL", __func__);
235 return -1;
236 }
237 ALOGI("%s: exit", __func__);
238 return ucMessageLength;
239}
240
241ANTStatus ant_rx_check()
242{
James Bootsmac3378cc2017-09-19 17:10:11 -0600243 ALOGV("%s: start", __func__);
James Bootsma84a310b2017-11-20 13:58:01 -0700244 Lock lock(ant_hci.data_mtx);
James Bootsmac3378cc2017-09-19 17:10:11 -0600245 while (ant_hci.rx_processing == 0)
James Bootsma9eb78a32017-06-13 09:42:00 -0600246 {
James Bootsmac3378cc2017-09-19 17:10:11 -0600247 ant_hci.data_cond.wait_for(lock,std::chrono::milliseconds(POLL_TIMEOUT_MS));
248 if (ant_hci.state != ANT_RADIO_ENABLED)
249 {
250 return ANT_STATUS_NO_VALUE_AVAILABLE;
251 }
James Bootsma9eb78a32017-06-13 09:42:00 -0600252 }
James Bootsmac3378cc2017-09-19 17:10:11 -0600253 ALOGV("%s: exit rx_processing =%d", __func__,ant_hci.rx_processing);
254 return ANT_STATUS_SUCCESS;
James Bootsma9eb78a32017-06-13 09:42:00 -0600255}
256
257void ant_rx_clear()
258{
259 ALOGI("%s: start", __func__);
260 Lock lk(ant_hci.rx_mtx);
261 ant_hci.rx_processing = false;
262 ant_hci.rx_cond.notify_all();
263 ALOGI("%s: exit", __func__);
264}
265
266void ant_interface_init()
267{
268 ALOGI("%s: start", __func__);
269 bool status;
270 status = hci_initialize();
271 if (status)
272 {
273 ALOGV("%s waiting for iniialization complete hci state: %d ", __func__, ant_hci.state);
274 Lock lk(ant_hci.on_mtx);
275 while(ant_hci.state == ANT_RADIO_ENABLING)
276 {
277 ant_hci.on_cond.wait(lk);
278 ALOGV(LOG_TAG,"%s:after on_cond wait ",__func__);
279 }
280 } else {
281 ALOGE(LOG_TAG,"%s:Failed ",__func__);
282 ant_hci.state = ANT_RADIO_DISABLED;
283 }
284 ALOGI(LOG_TAG,"%s:exit ",__func__);
285}