1 /******************************************************************************
2 *
3 * Copyright (C) 2009-2018 Realtek Corporation.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18 /******************************************************************************
19 *
20 * Filename: poll.c
21 *
22 * Description: Contains host & controller handshake implementation
23 *
24 ******************************************************************************/
25
26 #define LOG_TAG "bt_poll"
27
28 #include <utils/Log.h>
29 #include <signal.h>
30 #include <stdlib.h>
31 #include <time.h>
32 #include "bt_hci_bdroid.h"
33 //#include "bt_utils.h"
34 #include "rtk_poll.h"
35
36 /******************************************************************************
37 ** Constants & Macros
38 ******************************************************************************/
39 #ifndef BTPOLL_DBG
40 #define BTPOLL_DBG false
41 #endif
42
43 #if (BTPOLL_DBG == true)
44 #define BTPOLLDBG(param, ...) \
45 { \
46 HILOGD(param, ##__VA_ARGS__); \
47 }
48 #else
49 #define BTPOLLDBG(param, ...) \
50 { \
51 }
52 #endif
53
54 #ifndef ENABLE_BT_POLL_IN_ACTIVE_MODE
55 #define ENABLE_BT_POLL_IN_ACTIVE_MODE false
56 #endif
57
58 #ifndef DEFAULT_POLL_IDLE_TIMEOUT
59 #define DEFAULT_POLL_IDLE_TIMEOUT 2500
60 #endif
61
62 volatile uint32_t rtkbt_heartbeat_noack_num = 0;
63 volatile uint32_t rtkbt_heartbeat_evt_seqno = 0xffffffff;
64
65 timed_out poll_idle_timeout;
66
67 /******************************************************************************
68 ** Externs
69 ******************************************************************************/
70
71 /******************************************************************************
72 ** Local type definitions
73 ******************************************************************************/
74
75 /* Poll state */
76 enum
77 {
78 POLL_DISABLED = 0, /* initial state */
79 POLL_ENABLED,
80 };
81
82 /* poll control block */
83 typedef struct
84 {
85 uint8_t state; /* poll state */
86 uint8_t timer_created;
87 timer_t timer_id;
88 uint32_t timeout_ms;
89 } bt_poll_cb_t;
90
91 extern int timer_create(clockid_t clockid, struct sigevent *sevp,
92 timer_t *timerid);
93 extern int timer_delete(timer_t timerid);
94
95 int timer_settime(timer_t timerid, int flags,
96 const struct itimerspec *new_value,
97 struct itimerspec *old_value);
98 /******************************************************************************
99 ** Static variables
100 ******************************************************************************/
101
102 static bt_poll_cb_t bt_poll_cb;
103
104 /******************************************************************************
105 ** Poll Static Functions
106 ******************************************************************************/
107
108 /*******************************************************************************
109 **
110 ** Function poll_timer_stop
111 **
112 ** Description stop timer if allowed
113 **
114 ** Returns None
115 **
116 *******************************************************************************/
poll_timer_stop(void)117 static void poll_timer_stop(void)
118 {
119 int status;
120 struct itimerspec ts;
121
122 HILOGI("poll_timer_stop: timer_created %d", bt_poll_cb.timer_created);
123
124 if (bt_poll_cb.timer_created == true)
125 {
126 ts.it_value.tv_sec = 0;
127 ts.it_value.tv_nsec = 0;
128 ts.it_interval.tv_sec = 0;
129 ts.it_interval.tv_nsec = 0;
130
131 status = timer_settime(bt_poll_cb.timer_id, 0, &ts, 0);
132 if (status == -1)
133 HILOGE("[STOP] Failed to set poll idle timeout");
134 }
135 }
136
137 /*****************************************************************************
138 ** POLL Interface Functions
139 *****************************************************************************/
140
141 /*******************************************************************************
142 **
143 ** Function poll_init
144 **
145 ** Description Init bt poll
146 **
147 ** Returns None
148 **
149 *******************************************************************************/
poll_init(timed_out ptr_timeout,uint32_t timeout)150 void poll_init(timed_out ptr_timeout, uint32_t timeout)
151 {
152 memset((void *)&bt_poll_cb, 0, sizeof(bt_poll_cb_t));
153 poll_idle_timeout = ptr_timeout;
154 bt_poll_cb.state = POLL_DISABLED;
155 bt_poll_cb.timeout_ms = timeout;
156
157 HILOGI("poll_init: state %d, timeout %d ms,timeout=%d", bt_poll_cb.state, bt_poll_cb.timeout_ms, timeout);
158 }
159
160 /*******************************************************************************
161 **
162 ** Function poll_cleanup
163 **
164 ** Description Poll clean up
165 **
166 ** Returns None
167 **
168 *******************************************************************************/
poll_cleanup(void)169 void poll_cleanup(void)
170 {
171 HILOGI("poll_cleanup: timer_created %d", bt_poll_cb.timer_created);
172
173 if (bt_poll_cb.timer_created == true)
174 {
175 timer_delete(bt_poll_cb.timer_id);
176 }
177 }
178
179 /*******************************************************************************
180 **
181 ** Function poll_enable
182 **
183 ** Description Enalbe/Disable poll
184 **
185 ** Returns None
186 **
187 *******************************************************************************/
poll_enable(uint8_t turn_on)188 void poll_enable(uint8_t turn_on)
189 {
190 HILOGI("poll_enable: turn_on %d, state %d", turn_on, bt_poll_cb.state);
191
192 if ((turn_on == true) && (bt_poll_cb.state == POLL_ENABLED))
193 {
194 HILOGI("poll_enable: poll is already on!!!");
195 return;
196 }
197 else if ((turn_on == false) && (bt_poll_cb.state == POLL_DISABLED))
198 {
199 HILOGI("poll_enable: poll is already off!!!");
200 return;
201 }
202
203 if (turn_on == false)
204 {
205 poll_timer_stop();
206 bt_poll_cb.state = POLL_DISABLED;
207 }
208 else
209 {
210 /* start poll timer when poll_timer_flush invoked first time */
211 bt_poll_cb.state = POLL_ENABLED;
212 }
213 }
214
215 /*******************************************************************************
216 **
217 ** Function poll_timer_flush
218 **
219 ** Description Called to delay notifying Bluetooth chip.
220 ** Normally this is called when there is data to be sent
221 ** over HCI.
222 **
223 ** Returns None
224 **
225 *******************************************************************************/
poll_timer_flush(void)226 void poll_timer_flush(void)
227 {
228 int status;
229 struct itimerspec ts;
230 struct sigevent se;
231
232 memset(&se, 0, sizeof(struct sigevent));
233 BTPOLLDBG("poll_timer_flush: state %d", bt_poll_cb.state);
234
235 if (bt_poll_cb.state != POLL_ENABLED)
236 return;
237
238 if (bt_poll_cb.timer_created == false)
239 {
240 se.sigev_notify = SIGEV_THREAD;
241 se.sigev_value.sival_ptr = &bt_poll_cb.timer_id;
242 se.sigev_notify_function = poll_idle_timeout;
243 se.sigev_notify_attributes = NULL;
244
245 status = timer_create(CLOCK_MONOTONIC, &se, &bt_poll_cb.timer_id);
246
247 if (status == 0)
248 bt_poll_cb.timer_created = true;
249 }
250 #if (defined(ENABLE_BT_POLL_IN_ACTIVE_MODE) && (ENABLE_BT_POLL_IN_ACTIVE_MODE == false))
251 if (bt_poll_cb.timer_created == true)
252 {
253 ts.it_value.tv_sec = bt_poll_cb.timeout_ms / 1000;
254 ts.it_value.tv_nsec = 1000 * 1000 * (bt_poll_cb.timeout_ms % 1000);
255 ts.it_interval.tv_sec = 0;
256 ts.it_interval.tv_nsec = 0;
257
258 status = timer_settime(bt_poll_cb.timer_id, 0, &ts, 0);
259 if (status == -1)
260 HILOGE("[Flush] Failed to set poll idle timeout");
261 }
262 #endif
263 }
264