blob: 6647f8b4a03ffe5855fff63b53c93bad6a542114 [file] [log] [blame]
Satish kumar sugasibf9558e2016-05-10 14:30:17 -07001/*
2 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
31 * FMhal service used to access RFKILL
32
33**/
34
35#include <cutils/log.h>
36#include <sys/socket.h>
37#include <cutils/sockets.h>
38#include <pthread.h>
39#include <sys/select.h>
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <stdlib.h>
43#include <termios.h>
44#include <fcntl.h>
45#include <sys/un.h>
46#include <sys/eventfd.h>
47#include <errno.h>
48#include <string.h>
49
50#include <cutils/properties.h>
51#include "private/android_filesystem_config.h"
52
53
54//#include "bt_hci_bdroid.h"
55#include "bt_vendor_lib.h"
56#include "fm_hci.h"
57#include "wcnss_fmhci.h"
58#include <dlfcn.h>
59
60
61#define LOG_TAG "FMHalService"
62
63#define FM_HAL_SOCK "fmhal_sock"
64
65
66#define BT_SSR_TRIGGERED 0xee
67
68#define FM_POWER_OFF 0x01
69#define FM_POWER_ON 0x02
70#define FM_USERIAL_OPEN 0x03
71#define FM_USERIAL_CLOSE 0x04
72
73#define FM_CMD_PACKET_TYPE 0x11
74#define FM_EVT_PACKET_TYPE 0x14
75
76#ifndef BLUETOOTH_UID
77#define BLUETOOTH_UID 1002
78#endif
79#ifndef SYSTEM_UID
80#define SYSTEM_UID 1000
81#endif
82
83#ifndef ROOT_UID
84#define ROOT_UID 0
85#endif
86
87pthread_mutex_t signal_mutex;
88
89bt_vendor_interface_t *fm_if = NULL;
90int remote_fm_hal_fd;
91
92int do_write(int fd, unsigned char *buf,int len);
93
94unsigned char reset_cmpl[] = {0x04, 0x0e, 0x04, 0x01,0x03, 0x0c, 0x00};
95
96static int extract_uid(int uuid)
97{
98 int userid;
99 int appid;
100
101 appid = userid = uuid % AID_USER;
102 if (userid > BLUETOOTH_UID)
103 {
104 appid = userid % AID_APP;
105 }
106 ALOGD("%s appid = %d",__func__,appid);
107 return appid;
108}
109 void service_cleanup()
110{
111 char ref_count[PROPERTY_VALUE_MAX];
112 char cleanup[PROPERTY_VALUE_MAX];
113 int ref_val,clean;
114
115 ALOGE("Service is stopped ");
116 property_get("wc_transport.clean_up", cleanup, "0");
117 property_set("wc_transport.fm_service_status", "0");
118 property_set("wc_transport.start_fmhci", "0");
119 property_set("wc_transport.fm_power_status", "0");
120 clean = atoi(cleanup);
121 ALOGE("clean Value = %d",clean);
122}
123
124static int establish_fm_remote_socket(char *name)
125{
126 int fd = -1;
127 struct sockaddr_un client_address;
128 socklen_t clen;
129 int sock_id, ret;
130 struct ucred creds;
131 int c_uid;
132 ALOGI("%s(%s) Entry ", __func__, name);
133
134 sock_id = socket(AF_LOCAL, SOCK_STREAM, 0);
135 if (sock_id < 0) {
136 ALOGE("%s: server Socket creation failure", __func__);
137 return fd;
138 }
139
140 ALOGI("convert name to android abstract name:%s %d", name, sock_id);
141 if (socket_local_server_bind(sock_id,
142 name, ANDROID_SOCKET_NAMESPACE_ABSTRACT) >= 0) {
143 if (listen(sock_id, 5) == 0) {
144 ALOGI("listen to local socket:%s, fd:%d", name, sock_id);
145 } else {
146 ALOGE("listen to local socket:failed");
147 close(sock_id);
148 return fd;
149 }
150 } else {
151 close(sock_id);
152 ALOGE("%s: server bind failed for socket : %s", __func__, name);
153 return fd;
154 }
155
156 clen = sizeof(client_address);
157 /*Indicate that, server is ready to accept*/
158 property_set("wc_transport.fm_service_status", "1");
159 ALOGI("%s: wc_transport.fm_service_status set to 1 ", __func__);
160 ALOGI("%s: before accept_server_socket", name);
161 fd = accept(sock_id, (struct sockaddr *)&client_address, &clen);
162 if (fd > 0) {
163 ALOGI("%s accepted fd:%d for server fd:%d", name, fd, sock_id);
164 close(sock_id);
165
166 memset(&creds, 0, sizeof(creds));
167 socklen_t szCreds = sizeof(creds);
168 ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);
169 if (ret < 0) {
170 ALOGE("%s: error getting remote socket creds: %d\n", __func__, ret);
171 close(fd);
172 return -1;
173 }
174 c_uid = creds.uid;
175 if (c_uid > BLUETOOTH_UID)
176 c_uid = extract_uid(creds.uid);
177 if (c_uid != BLUETOOTH_UID && c_uid != SYSTEM_UID
178 && c_uid != ROOT_UID) {
179 ALOGE("%s: client doesn't have required credentials", __func__);
180 ALOGE("<%s req> client uid: %d", name, creds.uid);
181 close(fd);
182 return -1;
183 }
184
185 ALOGI("%s: Remote socket credentials: %d\n", __func__, creds.uid);
186 return fd;
187 } else {
188 ALOGE("BTC accept failed fd:%d sock d:%d error %s", fd, sock_id, strerror(errno));
189 close(sock_id);
190 return fd;
191 }
192
193 close(sock_id);
194 return fd;
195}
196
197
198int handle_fmcommand_writes(int fd) {
199 ALOGI("%s: ", __func__);
200 unsigned char first_byte;
201 int retval,val;
202 int fd_array[CH_MAX];
203
204 ALOGE("%s: FMHAL: read 1st byte to determine the power on/off ", __func__);
205
206 retval = read (fd, &first_byte, 1);
207 if (retval < 0) {
208 ALOGE("%s:read returns err: %d\n", __func__,retval);
209 return -1;
210 }
211 if (retval == 0) {
212 ALOGE("%s: This indicates the close of other end", __func__);
213 return -99;
214 }
215
216 ALOGE("%s: FM command type: 0x%x", __func__, first_byte);
217 switch(first_byte) {
218 case FM_POWER_OFF:
219 ALOGE("%s: Received power off command from FM stack: %d", __func__, first_byte);
220 val = 0;
221 retval = fm_if->op(BT_VND_OP_POWER_CTRL, &val);
222 if (retval < 0)
223 {
224 ALOGE("Failed to turn off power from bt vendor interface");
225 // return -1;
226 }
227 else {
228 property_set("wc_transport.fm_power_status", "0");
229 retval = -99;
230 }
231 break;
232
233 case FM_POWER_ON:
234 ALOGE("%s: Received power ON command from FM stack: %d", __func__, first_byte);
235 val = 1;
236 retval =fm_if->op(FM_VND_OP_POWER_CTRL, &val);
237 if (retval < 0)
238 {
239 ALOGE("Failed to turn on power from bt vendor interface");
240 }
241 else
242 property_set("wc_transport.fm_power_status", "1");
243 break;
244 default:
245 ALOGE("%s: Unexpected data format!!",__func__);
246 retval = -1;
247 }
248 return retval;
249}
250
251
252int do_read(int fd, unsigned char* buf, size_t len) {
253 int bytes_left, bytes_read = 0, read_offset;
254
255 bytes_left = len;
256 read_offset = 0;
257
258 do {
259 bytes_read = read(fd, buf+read_offset, bytes_left);
260 if (bytes_read < 0) {
261 ALOGE("%s: Read error: %d (%s)", __func__, bytes_left, strerror(errno));
262 return -1;
263 } else if (bytes_read == 0) {
264 ALOGE("%s: read returned 0, err = %s, read bytes: %d, expected: %d",
265 __func__, strerror(errno), (len-bytes_left), len);
266 return (len-bytes_left);
267 }
268 else {
269 if (bytes_read < bytes_left) {
270 ALOGV("Still there are %d bytes to read", bytes_left-bytes_read);
271 bytes_left = bytes_left-bytes_read;
272 read_offset = read_offset+bytes_read;
273 } else {
274 ALOGV("%s: done with read",__func__);
275 break;
276 }
277 }
278 }while(1);
279 return len;
280}
281
282int do_write(int fd, unsigned char *buf,int len)
283{
284 int ret = 0;
285 int write_offset = 0;
286 int write_len = len;
287 do {
288 ret = write(fd, buf+write_offset, write_len);
289 if (ret < 0)
290 {
291 ALOGE("%s: write failed ret = %d err = %s",__func__,ret,strerror(errno));
292 return -1;
293
294 } else if (ret == 0) {
295 ALOGE("%s: Write returned 0, err = %s, Written bytes: %d, expected: %d",
296 __func__, strerror(errno), (len-write_len), len);
297 return (len-write_len);
298
299 } else {
300 if (ret < write_len)
301 {
302 ALOGD("%s, Write pending,do write ret = %d err = %s",__func__,ret,
303 strerror(errno));
304 write_len = write_len - ret;
305 write_offset = ret;
306 } else if (ret > write_len) {
307 ALOGE("%s: FATAL wrote more than expected: written bytes: %d expected: %d",
308 __func__, write_len, ret);
309 break;
310 } else {
311 ALOGV("Write successful");
312 break;
313 }
314 }
315 } while(1);
316 return len;
317}
318
319void vnd_load_if()
320{
321 void *dlhandle;
322 unsigned char bdaddr[] = {0xaa, 0xbb, 0xcc, 0x11, 0x22, 0x33};
323
324 dlhandle = dlopen("libbt-vendor.so", RTLD_NOW);
325 if (!dlhandle)
326 {
327 ALOGE("!!! Failed to load libbt-vendor.so !!!");
328 return;
329 }
330
331 fm_if = (bt_vendor_interface_t *) dlsym(dlhandle, "BLUETOOTH_VENDOR_LIB_INTERFACE");
332 if (!fm_if)
333 {
334 ALOGE("!!! Failed to get bt vendor interface !!!");
335 return;
336 }
337
338 ALOGI("FM-HCI: Registering the WCNSS HAL library by passing CBs and BD addr.");
339 fm_if->init(&fmhci_vendor_callbacks, bdaddr);
340}
341
342
343int main() {
344 fd_set client_fds;
Smriti Guptac4750ad2016-07-08 12:05:57 +0530345 int retval = -1, n;
Satish kumar sugasibf9558e2016-05-10 14:30:17 -0700346
347 ALOGI("%s: Entry ", __func__);
348 ALOGI("FM HAL SERVICE: Loading the WCNSS HAL library...");
349 vnd_load_if();
350 ALOGI("create socket");
351 remote_fm_hal_fd = establish_fm_remote_socket(FM_HAL_SOCK);
352 if (remote_fm_hal_fd < 0) {
353 ALOGE("%s: invalid remote socket", __func__);
354 return -1;
355 }
356
357 FD_ZERO(&client_fds);
358 FD_SET(remote_fm_hal_fd, &client_fds);
359
360 do {
361 ALOGI("%s: Step 1-FM-HAL SERVICE: Waiting for FM HAL cmd ", __func__);
362 n = select(remote_fm_hal_fd+1, &client_fds, NULL, NULL, NULL);
363 if(n < 0){
364 ALOGE("Select: failed: %s", strerror(errno));
365 break;
366 }
367 ALOGI("%s: Step 2-FM-HAL SERVICE: FM POWER CMD available for processing...\n", __func__);
368 if (FD_ISSET(remote_fm_hal_fd, &client_fds)) {
369 retval = handle_fmcommand_writes(remote_fm_hal_fd);
370 ALOGI("%s: handle_fmcommand_writes . %d", __func__, retval);
371 if(retval < 0) {
372 if (retval == -99) {
373 ALOGI("%s:End of wait loop", __func__);
374 break;
375 }
376 ALOGI("%s: handle_fmcommand_writes returns: %d: ", __func__, retval);
377 // break;
378 }
379 }
380 } while(1);
381
382 service_cleanup();
383 ALOGI("%s: FM turned off or power off failed .service kill itself", __func__);
384 close(remote_fm_hal_fd);
385 remote_fm_hal_fd = 0;
386
387 ALOGI("%s: Exit: %d", __func__, retval);
388 return retval;
389}
390