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 "rtk_poll.h"
34
35 /******************************************************************************
36 ** Constants & Macros
37 ******************************************************************************/
38 #ifndef BTPOLL_DBG
39 #define BTPOLL_DBG false
40 #endif
41
42 #if (BTPOLL_DBG == true)
43 #define BTPOLLDBG(param, ...) \
44 { \
45 HILOGD(param, ##__VA_ARGS__); \
46 }
47 #else
48 #define BTPOLLDBG(param, ...) \
49 { \
50 }
51 #endif
52
53 #ifndef ENABLE_BT_POLL_IN_ACTIVE_MODE
54 #define ENABLE_BT_POLL_IN_ACTIVE_MODE false
55 #endif
56
57 #ifndef DEFAULT_POLL_IDLE_TIMEOUT
58 #define DEFAULT_POLL_IDLE_TIMEOUT 2500
59 #endif
60
61 volatile uint32_t rtkbt_heartbeat_noack_num = 0;
62 volatile uint32_t rtkbt_heartbeat_evt_seqno = 0xffffffff;
63
64 timed_out poll_idle_timeout;
65
66 /******************************************************************************
67 ** Externs
68 ******************************************************************************/
69
70 /******************************************************************************
71 ** Local type definitions
72 ******************************************************************************/
73
74 /* Poll state */
75 enum {
76 POLL_DISABLED = 0, /* initial state */
77 POLL_ENABLED,
78 };
79
80 /* poll control block */
81 typedef struct {
82 uint8_t state; /* poll state */
83 uint8_t timer_created;
84 timer_t timer_id;
85 uint32_t timeout_ms;
86 } bt_poll_cb_t;
87
88 /******************************************************************************
89 ** Static variables
90 ******************************************************************************/
91
92 static bt_poll_cb_t bt_poll_cb;
93
94 /******************************************************************************
95 ** Poll Static Functions
96 ******************************************************************************/
97
98 /*******************************************************************************
99 **
100 ** Function poll_timer_stop
101 **
102 ** Description stop timer if allowed
103 **
104 ** Returns None
105 **
106 *******************************************************************************/
poll_timer_stop(void)107 static void poll_timer_stop(void)
108 {
109 int status;
110 struct itimerspec ts;
111
112 HILOGI("poll_timer_stop: timer_created %d", bt_poll_cb.timer_created);
113
114 if (bt_poll_cb.timer_created == true) {
115 ts.it_value.tv_sec = 0;
116 ts.it_value.tv_nsec = 0;
117 ts.it_interval.tv_sec = 0;
118 ts.it_interval.tv_nsec = 0;
119
120 status = timer_settime(bt_poll_cb.timer_id, 0, &ts, 0);
121 if (status == -1) {
122 HILOGE("[STOP] Failed to set poll idle timeout");
123 }
124 }
125 }
126
127 /*****************************************************************************
128 ** POLL Interface Functions
129 *****************************************************************************/
130
131 /*******************************************************************************
132 **
133 ** Function poll_init
134 **
135 ** Description Init bt poll
136 **
137 ** Returns None
138 **
139 *******************************************************************************/
poll_init(timed_out ptr_timeout,uint32_t timeout)140 void poll_init(timed_out ptr_timeout, uint32_t timeout)
141 {
142 (void)memset_s((void *)&bt_poll_cb, sizeof(bt_poll_cb_t), 0, sizeof(bt_poll_cb_t));
143 poll_idle_timeout = ptr_timeout;
144 bt_poll_cb.state = POLL_DISABLED;
145 bt_poll_cb.timeout_ms = timeout;
146
147 HILOGI("poll_init: state %d, timeout %d ms,timeout=%d", bt_poll_cb.state, bt_poll_cb.timeout_ms, timeout);
148 }
149
150 /*******************************************************************************
151 **
152 ** Function poll_cleanup
153 **
154 ** Description Poll clean up
155 **
156 ** Returns None
157 **
158 *******************************************************************************/
poll_cleanup(void)159 void poll_cleanup(void)
160 {
161 HILOGI("poll_cleanup: timer_created %d", bt_poll_cb.timer_created);
162
163 if (bt_poll_cb.timer_created == true) {
164 timer_delete(bt_poll_cb.timer_id);
165 }
166 }
167
168 /*******************************************************************************
169 **
170 ** Function poll_enable
171 **
172 ** Description Enalbe/Disable poll
173 **
174 ** Returns None
175 **
176 *******************************************************************************/
poll_enable(uint8_t turn_on)177 void poll_enable(uint8_t turn_on)
178 {
179 HILOGI("poll_enable: turn_on %d, state %d", turn_on, bt_poll_cb.state);
180
181 if ((turn_on == true) && (bt_poll_cb.state == POLL_ENABLED)) {
182 HILOGI("poll_enable: poll is already on!!!");
183 return;
184 } else if ((turn_on == false) && (bt_poll_cb.state == POLL_DISABLED)) {
185 HILOGI("poll_enable: poll is already off!!!");
186 return;
187 }
188
189 if (turn_on == false) {
190 poll_timer_stop();
191 bt_poll_cb.state = POLL_DISABLED;
192 } else {
193 /* start poll timer when poll_timer_flush invoked first time */
194 bt_poll_cb.state = POLL_ENABLED;
195 }
196 }
197
198 /*******************************************************************************
199 **
200 ** Function poll_timer_flush
201 **
202 ** Description Called to delay notifying Bluetooth chip.
203 ** Normally this is called when there is data to be sent
204 ** over HCI.
205 **
206 ** Returns None
207 **
208 *******************************************************************************/
poll_timer_flush(void)209 void poll_timer_flush(void)
210 {
211 int status;
212 struct itimerspec ts;
213 struct sigevent se;
214
215 (void)memset_s(&se, sizeof(struct sigevent), 0, sizeof(struct sigevent));
216 BTPOLLDBG("poll_timer_flush: state %d", bt_poll_cb.state);
217
218 if (bt_poll_cb.state != POLL_ENABLED) {
219 return;
220 }
221
222 if (bt_poll_cb.timer_created == false) {
223 se.sigev_notify = SIGEV_THREAD;
224 se.sigev_value.sival_ptr = &bt_poll_cb.timer_id;
225 se.sigev_notify_function = poll_idle_timeout;
226 se.sigev_notify_attributes = NULL;
227
228 status = timer_create(CLOCK_MONOTONIC, &se, &bt_poll_cb.timer_id);
229 if (status == 0) {
230 bt_poll_cb.timer_created = true;
231 }
232 }
233 #if (defined(ENABLE_BT_POLL_IN_ACTIVE_MODE) && (ENABLE_BT_POLL_IN_ACTIVE_MODE == false))
234 if (bt_poll_cb.timer_created == true) {
235 ts.it_value.tv_sec = bt_poll_cb.timeout_ms / 1000L;
236 ts.it_value.tv_nsec = 1000L * 1000L * (bt_poll_cb.timeout_ms % 1000L);
237 ts.it_interval.tv_sec = 0;
238 ts.it_interval.tv_nsec = 0;
239
240 status = timer_settime(bt_poll_cb.timer_id, 0, &ts, 0);
241 if (status == -1) {
242 HILOGE("[Flush] Failed to set poll idle timeout");
243 }
244 }
245 #endif
246 }
247