blob: 50e03ba6a0f629e55688572168f687df49607475 [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 Bootsma9eb78a32017-06-13 09:42:00 -0600190 anthci->close();
191 }
James Bootsmac3378cc2017-09-19 17:10:11 -0600192 ant_hci.state = ANT_RADIO_DISABLED;
James Bootsma9eb78a32017-06-13 09:42:00 -0600193 ant_rx_clear();
194 anthci =nullptr;
James Bootsma9eb78a32017-06-13 09:42:00 -0600195 ALOGI("%s: exit", __func__);
196}
197
198ANT_UINT ant_get_status()
199{
200 return ant_hci.state;
201}
202
203ANTStatus ant_tx_write(ANT_U8 *pucTxMessage,ANT_U8 ucMessageLength)
204{
205 AntPacket data;
206 ANT_U8 packet_type;
207 ALOGI("%s: start", __func__);
208 packet_type = *pucTxMessage;
209 ALOGV("%s: proto type :%d", __func__, packet_type);
210 if (anthci != nullptr)
211 {
James Bootsma7b86e792017-08-10 11:38:40 -0600212 data.setToExternal(pucTxMessage+1, ucMessageLength-1);
James Bootsma9eb78a32017-06-13 09:42:00 -0600213 if (packet_type == ANT_DATA_TYPE_PACKET)
214 {
215 anthci->sendAntData(data);
216 } else {
217 anthci->sendAntControl(data);
218 }
219 } else {
220 ALOGE("%s: antHci is NULL", __func__);
221 return -1;
222 }
223 ALOGI("%s: exit", __func__);
224 return ucMessageLength;
225}
226
227ANTStatus ant_rx_check()
228{
James Bootsmac3378cc2017-09-19 17:10:11 -0600229 ALOGV("%s: start", __func__);
James Bootsma9eb78a32017-06-13 09:42:00 -0600230 if (ant_hci.rx_processing)
231 {
232 return ANT_STATUS_SUCCESS;
233 }
James Bootsmac3378cc2017-09-19 17:10:11 -0600234 while (ant_hci.rx_processing == 0)
James Bootsma9eb78a32017-06-13 09:42:00 -0600235 {
James Bootsmac3378cc2017-09-19 17:10:11 -0600236 std::unique_lock< std::mutex> lock(ant_hci.data_mtx);
237 ant_hci.data_cond.wait_for(lock,std::chrono::milliseconds(POLL_TIMEOUT_MS));
238 if (ant_hci.state != ANT_RADIO_ENABLED)
239 {
240 return ANT_STATUS_NO_VALUE_AVAILABLE;
241 }
James Bootsma9eb78a32017-06-13 09:42:00 -0600242 }
James Bootsmac3378cc2017-09-19 17:10:11 -0600243 ALOGV("%s: exit rx_processing =%d", __func__,ant_hci.rx_processing);
244 return ANT_STATUS_SUCCESS;
James Bootsma9eb78a32017-06-13 09:42:00 -0600245}
246
247void ant_rx_clear()
248{
249 ALOGI("%s: start", __func__);
250 Lock lk(ant_hci.rx_mtx);
251 ant_hci.rx_processing = false;
252 ant_hci.rx_cond.notify_all();
253 ALOGI("%s: exit", __func__);
254}
255
256void ant_interface_init()
257{
258 ALOGI("%s: start", __func__);
259 bool status;
260 status = hci_initialize();
261 if (status)
262 {
263 ALOGV("%s waiting for iniialization complete hci state: %d ", __func__, ant_hci.state);
264 Lock lk(ant_hci.on_mtx);
265 while(ant_hci.state == ANT_RADIO_ENABLING)
266 {
267 ant_hci.on_cond.wait(lk);
268 ALOGV(LOG_TAG,"%s:after on_cond wait ",__func__);
269 }
270 } else {
271 ALOGE(LOG_TAG,"%s:Failed ",__func__);
272 ant_hci.state = ANT_RADIO_DISABLED;
273 }
274 ALOGI(LOG_TAG,"%s:exit ",__func__);
275}