1 /******************************************************************************
2 *
3 * Copyright (C) 2009-2012 Broadcom 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 *
21 * Filename: upio.c
22 *
23 * Description: Contains I/O functions, like
24 * rfkill control
25 * BT_WAKE/HOST_WAKE control
26 *
27 ******************************************************************************/
28
29 #define LOG_TAG "bt_upio"
30
31 #include <utils/Log.h>
32 #include <fcntl.h>
33 #include <errno.h>
34 #include <string.h>
35 #include <cutils/properties.h>
36 #include "bt_vendor_brcm.h"
37 #include "upio.h"
38 #include "userial_vendor.h"
39 #include <stdio.h>
40 #include <unistd.h>
41 #include <time.h>
42
43 /******************************************************************************
44 ** Constants & Macros
45 ******************************************************************************/
46
47 #ifndef UPIO_DBG
48 #define UPIO_DBG FALSE
49 #endif
50
51 #if (UPIO_DBG == TRUE)
52 #define UPIODBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
53 #else
54 #define UPIODBG(param, ...) {}
55 #endif
56
57 /******************************************************************************
58 ** Local type definitions
59 ******************************************************************************/
60
61 #if (BT_WAKE_VIA_PROC == TRUE)
62
63 /* proc fs node for enable/disable lpm mode */
64 #ifndef VENDOR_LPM_PROC_NODE
65 #define VENDOR_LPM_PROC_NODE "/proc/bluetooth/sleep/lpm"
66 #endif
67
68 /* proc fs node for notifying write request */
69 #ifndef VENDOR_BTWRITE_PROC_NODE
70 #define VENDOR_BTWRITE_PROC_NODE "/proc/bluetooth/sleep/btwrite"
71 #endif
72
73 /*
74 * Maximum btwrite assertion holding time without consecutive btwrite kicking.
75 * This value is correlative(shorter) to the in-activity timeout period set in
76 * the bluesleep LPM code. The current value used in bluesleep is 10sec.
77 */
78 #ifndef PROC_BTWRITE_TIMER_TIMEOUT_MS
79 #define PROC_BTWRITE_TIMER_TIMEOUT_MS 8000
80 #endif
81
82 /* lpm proc control block */
83 typedef struct
84 {
85 uint8_t btwrite_active;
86 uint8_t timer_created;
87 timer_t timer_id;
88 uint32_t timeout_ms;
89 } vnd_lpm_proc_cb_t;
90
91 static vnd_lpm_proc_cb_t lpm_proc_cb;
92 #endif
93
94 /******************************************************************************
95 ** Static variables
96 ******************************************************************************/
97
98 static uint8_t upio_state[UPIO_MAX_COUNT];
99 static int rfkill_id = -1;
100 static int bt_emul_enable = 0;
101 static char *rfkill_state_path = NULL;
102
103 /******************************************************************************
104 ** Static functions
105 ******************************************************************************/
106
107 /* for friendly debugging outpout string */
108 static char *lpm_mode[] = {
109 "UNKNOWN",
110 "disabled",
111 "enabled"
112 };
113
114 static char *lpm_state[] = {
115 "UNKNOWN",
116 "de-asserted",
117 "asserted"
118 };
119
120 /*****************************************************************************
121 ** Bluetooth On/Off Static Functions
122 *****************************************************************************/
is_emulator_context(void)123 static int is_emulator_context(void)
124 {
125 char value[PROPERTY_VALUE_MAX];
126
127 property_get("ro.boot.qemu", value, "0");
128 UPIODBG("is_emulator_context : %s", value);
129 if (strcmp(value, "1") == 0) {
130 return 1;
131 }
132 return 0;
133 }
134
is_rfkill_disabled(void)135 static int is_rfkill_disabled(void)
136 {
137 char value[PROPERTY_VALUE_MAX];
138
139 property_get("ro.rfkilldisabled", value, "0");
140 UPIODBG("is_rfkill_disabled ? [%s]", value);
141
142 if (strcmp(value, "1") == 0) {
143 return UPIO_BT_POWER_ON;
144 }
145
146 return UPIO_BT_POWER_OFF;
147 }
148
init_rfkill()149 static int init_rfkill()
150 {
151 char path[64];
152 char buf[16];
153 int fd, sz, id;
154
155 if (is_rfkill_disabled())
156 return -1;
157
158 for (id = 0; ; id++)
159 {
160 snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id);
161 fd = open(path, O_RDONLY);
162 if (fd < 0)
163 {
164 ALOGE("init_rfkill : open(%s) failed: %s (%d)\n", \
165 path, strerror(errno), errno);
166 return -1;
167 }
168
169 sz = read(fd, &buf, sizeof(buf));
170 close(fd);
171
172 if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0)
173 {
174 rfkill_id = id;
175 break;
176 }
177 }
178
179 asprintf(&rfkill_state_path, "/sys/class/rfkill/rfkill%d/state", rfkill_id);
180 return 0;
181 }
182
183 /*****************************************************************************
184 ** LPM Static Functions
185 *****************************************************************************/
186
187 #if (BT_WAKE_VIA_PROC == TRUE)
188 /*******************************************************************************
189 **
190 ** Function proc_btwrite_timeout
191 **
192 ** Description Timeout thread of proc/.../btwrite assertion holding timer
193 **
194 ** Returns None
195 **
196 *******************************************************************************/
proc_btwrite_timeout(union sigval arg)197 static void proc_btwrite_timeout(union sigval arg)
198 {
199 UPIODBG("..%s..", __FUNCTION__);
200 lpm_proc_cb.btwrite_active = FALSE;
201 /* drive LPM down; this timer should fire only when BT is awake; */
202 upio_set(UPIO_BT_WAKE, UPIO_DEASSERT, 1);
203 }
204
205 /******************************************************************************
206 **
207 ** Function upio_start_stop_timer
208 **
209 ** Description Arm user space timer in case lpm is left asserted
210 **
211 ** Returns None
212 **
213 *****************************************************************************/
upio_start_stop_timer(int action)214 void upio_start_stop_timer(int action) {
215 struct itimerspec ts;
216
217 if (action == UPIO_ASSERT) {
218 lpm_proc_cb.btwrite_active = TRUE;
219 if (lpm_proc_cb.timer_created == TRUE) {
220 ts.it_value.tv_sec = PROC_BTWRITE_TIMER_TIMEOUT_MS/1000;
221 ts.it_value.tv_nsec = 1000000*(PROC_BTWRITE_TIMER_TIMEOUT_MS%1000);
222 ts.it_interval.tv_sec = 0;
223 ts.it_interval.tv_nsec = 0;
224 }
225 } else {
226 /* unarm timer if writing 0 to lpm; reduce unnecessary user space wakeup */
227 memset(&ts, 0, sizeof(ts));
228 }
229
230 if (timer_settime(lpm_proc_cb.timer_id, 0, &ts, 0) == 0) {
231 UPIODBG("%s : timer_settime success", __FUNCTION__);
232 } else {
233 UPIODBG("%s : timer_settime failed", __FUNCTION__);
234 }
235 }
236 #endif
237
238 /*****************************************************************************
239 ** UPIO Interface Functions
240 *****************************************************************************/
241
242 /*******************************************************************************
243 **
244 ** Function upio_init
245 **
246 ** Description Initialization
247 **
248 ** Returns None
249 **
250 *******************************************************************************/
upio_init(void)251 void upio_init(void)
252 {
253 memset(upio_state, UPIO_UNKNOWN, UPIO_MAX_COUNT);
254 #if (BT_WAKE_VIA_PROC == TRUE)
255 memset(&lpm_proc_cb, 0, sizeof(vnd_lpm_proc_cb_t));
256 #endif
257 }
258
259 /*******************************************************************************
260 **
261 ** Function upio_cleanup
262 **
263 ** Description Clean up
264 **
265 ** Returns None
266 **
267 *******************************************************************************/
upio_cleanup(void)268 void upio_cleanup(void)
269 {
270 #if (BT_WAKE_VIA_PROC == TRUE)
271 if (lpm_proc_cb.timer_created == TRUE)
272 timer_delete(lpm_proc_cb.timer_id);
273
274 lpm_proc_cb.timer_created = FALSE;
275 #endif
276 }
277
278 /*******************************************************************************
279 **
280 ** Function upio_set_bluetooth_power
281 **
282 ** Description Interact with low layer driver to set Bluetooth power
283 ** on/off.
284 **
285 ** Returns 0 : SUCCESS or Not-Applicable
286 ** <0 : ERROR
287 **
288 *******************************************************************************/
upio_set_bluetooth_power(int on)289 int upio_set_bluetooth_power(int on)
290 {
291 int sz;
292 int fd = -1;
293 int ret = -1;
294 char buffer = '0';
295
296 switch(on)
297 {
298 case UPIO_BT_POWER_OFF:
299 buffer = '0';
300 break;
301
302 case UPIO_BT_POWER_ON:
303 buffer = '1';
304 break;
305 }
306
307 if (is_emulator_context())
308 {
309 /* if new value is same as current, return -1 */
310 if (bt_emul_enable == on)
311 return ret;
312
313 UPIODBG("set_bluetooth_power [emul] %d", on);
314
315 bt_emul_enable = on;
316 return 0;
317 }
318
319 /* check if we have rfkill interface */
320 if (is_rfkill_disabled())
321 return 0;
322
323 if (rfkill_id == -1)
324 {
325 if (init_rfkill())
326 return ret;
327 }
328
329 fd = open(rfkill_state_path, O_WRONLY);
330
331 if (fd < 0)
332 {
333 ALOGE("set_bluetooth_power : open(%s) for write failed: %s (%d)",
334 rfkill_state_path, strerror(errno), errno);
335 return ret;
336 }
337
338 sz = write(fd, &buffer, 1);
339
340 if (sz < 0) {
341 ALOGE("set_bluetooth_power : write(%s) failed: %s (%d)",
342 rfkill_state_path, strerror(errno),errno);
343 }
344 else
345 ret = 0;
346
347 if (fd >= 0)
348 close(fd);
349
350 return ret;
351 }
352
353
354 /*******************************************************************************
355 **
356 ** Function upio_set
357 **
358 ** Description Set i/o based on polarity
359 **
360 ** Returns None
361 **
362 *******************************************************************************/
upio_set(uint8_t pio,uint8_t action,uint8_t polarity)363 void upio_set(uint8_t pio, uint8_t action, uint8_t polarity)
364 {
365 int rc;
366 #if (BT_WAKE_VIA_PROC == TRUE)
367 int fd = -1;
368 char buffer;
369 #endif
370
371 UPIODBG("%s : pio %d action %d, polarity %d", __FUNCTION__, pio, action, polarity);
372
373 switch (pio)
374 {
375 case UPIO_LPM_MODE:
376 if (upio_state[UPIO_LPM_MODE] == action)
377 {
378 UPIODBG("LPM is %s already", lpm_mode[action]);
379 return;
380 }
381
382 upio_state[UPIO_LPM_MODE] = action;
383
384 #if (BT_WAKE_VIA_PROC == TRUE)
385 fd = open(VENDOR_LPM_PROC_NODE, O_WRONLY);
386
387 if (fd < 0)
388 {
389 ALOGE("upio_set : open(%s) for write failed: %s (%d)",
390 VENDOR_LPM_PROC_NODE, strerror(errno), errno);
391 return;
392 }
393
394 if (action == UPIO_ASSERT)
395 {
396 buffer = '1';
397 }
398 else
399 {
400 buffer = '0';
401
402 // delete btwrite assertion holding timer
403 if (lpm_proc_cb.timer_created == TRUE)
404 {
405 timer_delete(lpm_proc_cb.timer_id);
406 lpm_proc_cb.timer_created = FALSE;
407 }
408 }
409
410 if (write(fd, &buffer, 1) < 0)
411 {
412 ALOGE("upio_set : write(%s) failed: %s (%d)",
413 VENDOR_LPM_PROC_NODE, strerror(errno),errno);
414 }
415 #if (PROC_BTWRITE_TIMER_TIMEOUT_MS != 0)
416 else
417 {
418 if (action == UPIO_ASSERT)
419 {
420 // create btwrite assertion holding timer
421 if (lpm_proc_cb.timer_created == FALSE)
422 {
423 int status;
424 struct sigevent se;
425
426 se.sigev_notify = SIGEV_THREAD;
427 se.sigev_value.sival_ptr = &lpm_proc_cb.timer_id;
428 se.sigev_notify_function = proc_btwrite_timeout;
429 se.sigev_notify_attributes = NULL;
430
431 status = timer_create(CLOCK_MONOTONIC, &se,
432 &lpm_proc_cb.timer_id);
433
434 if (status == 0)
435 lpm_proc_cb.timer_created = TRUE;
436 }
437 }
438 }
439 #endif
440
441 if (fd >= 0)
442 close(fd);
443 #endif
444 break;
445
446 case UPIO_BT_WAKE:
447 if (upio_state[UPIO_BT_WAKE] == action)
448 {
449 UPIODBG("BT_WAKE is %s already", lpm_state[action]);
450
451 #if (BT_WAKE_VIA_PROC == TRUE)
452 if (lpm_proc_cb.btwrite_active == TRUE)
453 /*
454 * The proc btwrite node could have not been updated for
455 * certain time already due to heavy downstream path flow.
456 * In this case, we want to explicity touch proc btwrite
457 * node to keep the bt_wake assertion in the LPM kernel
458 * driver. The current kernel bluesleep LPM code starts
459 * a 10sec internal in-activity timeout timer before it
460 * attempts to deassert BT_WAKE line.
461 */
462 return;
463 #else
464 return;
465 #endif
466 }
467
468 upio_state[UPIO_BT_WAKE] = action;
469
470 #if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE)
471
472 userial_vendor_ioctl( ( (action==UPIO_ASSERT) ? \
473 USERIAL_OP_ASSERT_BT_WAKE : USERIAL_OP_DEASSERT_BT_WAKE),\
474 NULL);
475
476 #elif (BT_WAKE_VIA_PROC == TRUE)
477
478 /*
479 * Kick proc btwrite node only at UPIO_ASSERT
480 */
481 #if (BT_WAKE_VIA_PROC_NOTIFY_DEASSERT == FALSE)
482 if (action == UPIO_DEASSERT)
483 return;
484 #endif
485 fd = open(VENDOR_BTWRITE_PROC_NODE, O_WRONLY);
486
487 if (fd < 0)
488 {
489 ALOGE("upio_set : open(%s) for write failed: %s (%d)",
490 VENDOR_BTWRITE_PROC_NODE, strerror(errno), errno);
491 return;
492 }
493 #if (BT_WAKE_VIA_PROC_NOTIFY_DEASSERT == TRUE)
494 if (action == UPIO_DEASSERT)
495 buffer = '0';
496 else
497 #endif
498 buffer = '1';
499
500 if (write(fd, &buffer, 1) < 0)
501 {
502 ALOGE("upio_set : write(%s) failed: %s (%d)",
503 VENDOR_BTWRITE_PROC_NODE, strerror(errno),errno);
504 }
505 #if (PROC_BTWRITE_TIMER_TIMEOUT_MS != 0)
506 else
507 {
508 /* arm user space timer based on action */
509 upio_start_stop_timer(action);
510 }
511 #endif
512
513 #if (BT_WAKE_VIA_PROC_NOTIFY_DEASSERT == TRUE)
514 lpm_proc_cb.btwrite_active = TRUE;
515 #endif
516
517 UPIODBG("%s: proc btwrite assertion, buffer: %c, timer_armed %d %d",
518 __FUNCTION__, buffer, lpm_proc_cb.btwrite_active, lpm_proc_cb.timer_created);
519
520 if (fd >= 0)
521 close(fd);
522 #endif
523
524 break;
525
526 case UPIO_HOST_WAKE:
527 UPIODBG("upio_set: UPIO_HOST_WAKE");
528 break;
529 }
530 }
531
532
533