blob: d32f334443616c0c6e84ae72c500cc44ac108e38
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 <cutils/properties.h> |
35 | #include "bt_vendor_brcm.h" |
36 | #include "upio.h" |
37 | #include "userial_vendor.h" |
38 | |
39 | /****************************************************************************** |
40 | ** Constants & Macros |
41 | ******************************************************************************/ |
42 | |
43 | #ifndef UPIO_DBG |
44 | #define UPIO_DBG FALSE |
45 | #endif |
46 | |
47 | #if (UPIO_DBG == TRUE) |
48 | #define UPIODBG(param, ...) {ALOGD(param, ## __VA_ARGS__);} |
49 | #else |
50 | #define UPIODBG(param, ...) {} |
51 | #endif |
52 | |
53 | /****************************************************************************** |
54 | ** Local type definitions |
55 | ******************************************************************************/ |
56 | |
57 | /****************************************************************************** |
58 | ** Static variables |
59 | ******************************************************************************/ |
60 | |
61 | static uint8_t upio_state[UPIO_MAX_COUNT]; |
62 | static int rfkill_id = -1; |
63 | static int bt_emul_enable = 0; |
64 | static char *rfkill_state_path = NULL; |
65 | |
66 | /****************************************************************************** |
67 | ** Static functions |
68 | ******************************************************************************/ |
69 | |
70 | /* for friendly debugging outpout string */ |
71 | static char *lpm_state[] = { |
72 | "UNKNOWN", |
73 | "de-asserted", |
74 | "asserted" |
75 | }; |
76 | |
77 | /***************************************************************************** |
78 | ** Bluetooth On/Off Static Functions |
79 | *****************************************************************************/ |
80 | static int is_emulator_context(void) |
81 | { |
82 | char value[PROPERTY_VALUE_MAX]; |
83 | |
84 | property_get("ro.kernel.qemu", value, "0"); |
85 | UPIODBG("is_emulator_context : %s", value); |
86 | if (strcmp(value, "1") == 0) { |
87 | return 1; |
88 | } |
89 | return 0; |
90 | } |
91 | |
92 | static int is_rfkill_disabled(void) |
93 | { |
94 | char value[PROPERTY_VALUE_MAX]; |
95 | |
96 | property_get("ro.rfkilldisabled", value, "0"); |
97 | UPIODBG("is_rfkill_disabled ? [%s]", value); |
98 | |
99 | if (strcmp(value, "1") == 0) { |
100 | return UPIO_BT_POWER_ON; |
101 | } |
102 | |
103 | return UPIO_BT_POWER_OFF; |
104 | } |
105 | |
106 | static int init_rfkill() |
107 | { |
108 | char path[64]; |
109 | char buf[16]; |
110 | int fd, sz, id; |
111 | |
112 | if (is_rfkill_disabled()) |
113 | return -1; |
114 | |
115 | for (id = 0; ; id++) |
116 | { |
117 | snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id); |
118 | fd = open(path, O_RDONLY); |
119 | if (fd < 0) |
120 | { |
121 | ALOGE("init_rfkill : open(%s) failed: %s (%d)\n", \ |
122 | path, strerror(errno), errno); |
123 | return -1; |
124 | } |
125 | |
126 | sz = read(fd, &buf, sizeof(buf)); |
127 | close(fd); |
128 | |
129 | if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0) |
130 | { |
131 | rfkill_id = id; |
132 | break; |
133 | } |
134 | } |
135 | |
136 | asprintf(&rfkill_state_path, "/sys/class/rfkill/rfkill%d/state", rfkill_id); |
137 | return 0; |
138 | } |
139 | |
140 | /***************************************************************************** |
141 | ** LPM Static Functions |
142 | *****************************************************************************/ |
143 | |
144 | /***************************************************************************** |
145 | ** UPIO Interface Functions |
146 | *****************************************************************************/ |
147 | |
148 | /******************************************************************************* |
149 | ** |
150 | ** Function upio_init |
151 | ** |
152 | ** Description Initialization |
153 | ** |
154 | ** Returns None |
155 | ** |
156 | *******************************************************************************/ |
157 | void upio_init(void) |
158 | { |
159 | memset(upio_state, UPIO_UNKNOWN, UPIO_MAX_COUNT); |
160 | } |
161 | |
162 | /******************************************************************************* |
163 | ** |
164 | ** Function upio_cleanup |
165 | ** |
166 | ** Description Clean up |
167 | ** |
168 | ** Returns None |
169 | ** |
170 | *******************************************************************************/ |
171 | void upio_cleanup(void) |
172 | { |
173 | } |
174 | |
175 | /******************************************************************************* |
176 | ** |
177 | ** Function upio_set_bluetooth_power |
178 | ** |
179 | ** Description Interact with low layer driver to set Bluetooth power |
180 | ** on/off. |
181 | ** |
182 | ** Returns 0 : SUCCESS or Not-Applicable |
183 | ** <0 : ERROR |
184 | ** |
185 | *******************************************************************************/ |
186 | int upio_set_bluetooth_power(int on) |
187 | { |
188 | int sz; |
189 | int fd = -1; |
190 | int ret = -1; |
191 | char buffer = '0'; |
192 | |
193 | switch(on) |
194 | { |
195 | case UPIO_BT_POWER_OFF: |
196 | buffer = '0'; |
197 | break; |
198 | |
199 | case UPIO_BT_POWER_ON: |
200 | buffer = '1'; |
201 | break; |
202 | } |
203 | |
204 | if (is_emulator_context()) |
205 | { |
206 | /* if new value is same as current, return -1 */ |
207 | if (bt_emul_enable == on) |
208 | return ret; |
209 | |
210 | UPIODBG("set_bluetooth_power [emul] %d", on); |
211 | |
212 | bt_emul_enable = on; |
213 | return 0; |
214 | } |
215 | |
216 | /* check if we have rfkill interface */ |
217 | if (is_rfkill_disabled()) |
218 | return 0; |
219 | |
220 | if (rfkill_id == -1) |
221 | { |
222 | if (init_rfkill()) |
223 | return ret; |
224 | } |
225 | |
226 | fd = open(rfkill_state_path, O_WRONLY); |
227 | |
228 | if (fd < 0) |
229 | { |
230 | ALOGE("set_bluetooth_power : open(%s) for write failed: %s (%d)", |
231 | rfkill_state_path, strerror(errno), errno); |
232 | return ret; |
233 | } |
234 | |
235 | sz = write(fd, &buffer, 1); |
236 | |
237 | if (sz < 0) { |
238 | ALOGE("set_bluetooth_power : write(%s) failed: %s (%d)", |
239 | rfkill_state_path, strerror(errno),errno); |
240 | } |
241 | else |
242 | ret = 0; |
243 | |
244 | if (fd >= 0) |
245 | close(fd); |
246 | |
247 | return ret; |
248 | } |
249 | |
250 | |
251 | /******************************************************************************* |
252 | ** |
253 | ** Function upio_set |
254 | ** |
255 | ** Description Set i/o based on polarity |
256 | ** |
257 | ** Returns None |
258 | ** |
259 | *******************************************************************************/ |
260 | void upio_set(uint8_t pio, uint8_t action, uint8_t polarity) |
261 | { |
262 | int rc; |
263 | |
264 | switch (pio) |
265 | { |
266 | case UPIO_BT_WAKE: |
267 | |
268 | if (upio_state[UPIO_BT_WAKE] == action) |
269 | { |
270 | UPIODBG("BT_WAKE is %s already", lpm_state[action]); |
271 | return; |
272 | } |
273 | |
274 | upio_state[UPIO_BT_WAKE] = action; |
275 | |
276 | /**************************************** |
277 | * !!! TODO !!! |
278 | * |
279 | * === Custom Porting Required === |
280 | * |
281 | * Platform dependent user-to-kernel |
282 | * interface is required to set output |
283 | * state of physical BT_WAKE pin. |
284 | ****************************************/ |
285 | #if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE) |
286 | userial_vendor_ioctl( ( (action==UPIO_ASSERT) ? \ |
287 | USERIAL_OP_ASSERT_BT_WAKE : USERIAL_OP_DEASSERT_BT_WAKE),\ |
288 | NULL); |
289 | #endif |
290 | break; |
291 | |
292 | case UPIO_HOST_WAKE: |
293 | UPIODBG("upio_set: UPIO_HOST_WAKE"); |
294 | break; |
295 | } |
296 | } |
297 | |
298 | |
299 |