blob: 895d1a33c74e61114599fca525639ed3b497c70b [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
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: uipc.c
22 *
23 * Description: UIPC implementation for bluedroid
24 *
25 *****************************************************************************/
26
27#include <stdio.h>
28#include <string.h>
29#include <stdlib.h>
30
31#include <sys/stat.h>
32#include <unistd.h>
33#include <fcntl.h>
34
35#include <sys/socket.h>
36#include <sys/un.h>
Bhakthavatsala Raghavendra551b9bb2014-11-21 12:24:18 -080037#include <sys/ioctl.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080038#include <signal.h>
39#include <errno.h>
40#include <pthread.h>
41#include <sys/select.h>
42#include <sys/poll.h>
43#include <sys/mman.h>
44#include <sys/stat.h>
45#include <sys/prctl.h>
46
47
48#include "gki.h"
49#include "data_types.h"
50#include "uipc.h"
51
52#include <cutils/sockets.h>
53#include "audio_a2dp_hw.h"
Mike J. Chen5cd8bff2014-01-31 18:16:59 -080054#include "bt_utils.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080055
56/*****************************************************************************
57** Constants & Macros
58******************************************************************************/
59
60#define PCM_FILENAME "/data/test.pcm"
61
62#define MAX(a,b) ((a)>(b)?(a):(b))
63
64#define CASE_RETURN_STR(const) case const: return #const;
65
66#define UIPC_DISCONNECTED (-1)
67
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -070068#define UIPC_LOCK() /*BTIF_TRACE_EVENT(" %s lock", __FUNCTION__);*/ pthread_mutex_lock(&uipc_main.mutex);
69#define UIPC_UNLOCK() /*BTIF_TRACE_EVENT("%s unlock", __FUNCTION__);*/ pthread_mutex_unlock(&uipc_main.mutex);
The Android Open Source Project5738f832012-12-12 16:00:35 -080070
Elliott Hughes2408d9e2013-10-02 21:28:50 -070071#define SAFE_FD_ISSET(fd, set) (((fd) == -1) ? FALSE : FD_ISSET((fd), (set)))
72
Andre Eisenbachc5916e92014-11-07 15:46:04 -080073#define UIPC_FLUSH_BUFFER_SIZE 1024
74
The Android Open Source Project5738f832012-12-12 16:00:35 -080075/*****************************************************************************
76** Local type definitions
77******************************************************************************/
78
79typedef enum {
80 UIPC_TASK_FLAG_DISCONNECT_CHAN = 0x1,
81} tUIPC_TASK_FLAGS;
82
83typedef struct {
84 int srvfd;
85 int fd;
86 int read_poll_tmo_ms;
87 int task_evt_flags; /* event flags pending to be processed in read task */
88 tUIPC_EVENT cond_flags;
89 pthread_mutex_t cond_mutex;
90 pthread_cond_t cond;
91 tUIPC_RCV_CBACK *cback;
92} tUIPC_CHAN;
93
94typedef struct {
95 pthread_t tid; /* main thread id */
96 int running;
97 pthread_mutex_t mutex;
98
99 fd_set active_set;
100 fd_set read_set;
101 int max_fd;
102 int signal_fds[2];
103
104 tUIPC_CHAN ch[UIPC_CH_NUM];
105} tUIPC_MAIN;
106
107
108/*****************************************************************************
109** Static variables
110******************************************************************************/
111
112static tUIPC_MAIN uipc_main;
113
114
115/*****************************************************************************
116** Static functions
117******************************************************************************/
118
119static int uipc_close_ch_locked(tUIPC_CH_ID ch_id);
120
121/*****************************************************************************
122** Externs
123******************************************************************************/
124
125
126/*****************************************************************************
127** Helper functions
128******************************************************************************/
129
130
131const char* dump_uipc_event(tUIPC_EVENT event)
132{
133 switch(event)
134 {
135 CASE_RETURN_STR(UIPC_OPEN_EVT)
136 CASE_RETURN_STR(UIPC_CLOSE_EVT)
137 CASE_RETURN_STR(UIPC_RX_DATA_EVT)
138 CASE_RETURN_STR(UIPC_RX_DATA_READY_EVT)
139 CASE_RETURN_STR(UIPC_TX_DATA_READY_EVT)
140 default:
141 return "UNKNOWN MSG ID";
142 }
143}
144
145/*****************************************************************************
The Android Open Source Project5738f832012-12-12 16:00:35 -0800146** socket helper functions
147*****************************************************************************/
148
149static inline int create_server_socket(const char* name)
150{
151 int s = socket(AF_LOCAL, SOCK_STREAM, 0);
152
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700153 BTIF_TRACE_EVENT("create_server_socket %s", name);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800154
155 if(socket_local_server_bind(s, name, ANDROID_SOCKET_NAMESPACE_ABSTRACT) < 0)
156 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700157 BTIF_TRACE_EVENT("socket failed to create (%s)", strerror(errno));
Kim Schulz2a2701c2013-09-16 15:59:33 +0200158 close(s);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800159 return -1;
160 }
161
162 if(listen(s, 5) < 0)
163 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700164 BTIF_TRACE_EVENT("listen failed", strerror(errno));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800165 close(s);
166 return -1;
167 }
168
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700169 BTIF_TRACE_EVENT("created socket fd %d", s);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800170 return s;
171}
172
173static int accept_server_socket(int sfd)
174{
175 struct sockaddr_un remote;
176 struct pollfd pfd;
177 int fd;
Elliott Hughes730a4b22014-02-07 12:23:05 -0800178 socklen_t len = sizeof(struct sockaddr_un);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800179
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700180 BTIF_TRACE_EVENT("accept fd %d", sfd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800181
182 /* make sure there is data to process */
183 pfd.fd = sfd;
184 pfd.events = POLLIN;
185
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700186 if (TEMP_FAILURE_RETRY(poll(&pfd, 1, 0)) == 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800187 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700188 BTIF_TRACE_EVENT("accept poll timeout");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800189 return -1;
190 }
191
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700192 //BTIF_TRACE_EVENT("poll revents 0x%x", pfd.revents);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800193
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700194 if ((fd = TEMP_FAILURE_RETRY(accept(sfd, (struct sockaddr *)&remote, &len))) == -1)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800195 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700196 BTIF_TRACE_ERROR("sock accept failed (%s)", strerror(errno));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800197 return -1;
198 }
199
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700200 //BTIF_TRACE_EVENT("new fd %d", fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800201
202 return fd;
203}
204
205/*****************************************************************************
206**
207** uipc helper functions
208**
209*****************************************************************************/
210
211static int uipc_main_init(void)
212{
213 int i;
214 const pthread_mutexattr_t attr = PTHREAD_MUTEX_RECURSIVE;
215 pthread_mutex_init(&uipc_main.mutex, &attr);
216
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700217 BTIF_TRACE_EVENT("### uipc_main_init ###");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800218
219 /* setup interrupt socket pair */
220 if (socketpair(AF_UNIX, SOCK_STREAM, 0, uipc_main.signal_fds) < 0)
221 {
222 return -1;
223 }
224
225 FD_SET(uipc_main.signal_fds[0], &uipc_main.active_set);
226 uipc_main.max_fd = MAX(uipc_main.max_fd, uipc_main.signal_fds[0]);
227
228 for (i=0; i< UIPC_CH_NUM; i++)
229 {
230 tUIPC_CHAN *p = &uipc_main.ch[i];
231 p->srvfd = UIPC_DISCONNECTED;
232 p->fd = UIPC_DISCONNECTED;
233 p->task_evt_flags = 0;
234 pthread_cond_init(&p->cond, NULL);
235 pthread_mutex_init(&p->cond_mutex, NULL);
236 p->cback = NULL;
237 }
238
239 return 0;
240}
241
242void uipc_main_cleanup(void)
243{
244 int i;
245
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700246 BTIF_TRACE_EVENT("uipc_main_cleanup");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800247
248 close(uipc_main.signal_fds[0]);
249 close(uipc_main.signal_fds[1]);
250
251 /* close any open channels */
252 for (i=0; i<UIPC_CH_NUM; i++)
253 uipc_close_ch_locked(i);
254}
255
256
257
258/* check pending events in read task */
259static void uipc_check_task_flags_locked(void)
260{
261 int i;
262
263 for (i=0; i<UIPC_CH_NUM; i++)
264 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700265 //BTIF_TRACE_EVENT("CHECK TASK FLAGS %x %x", uipc_main.ch[i].task_evt_flags, UIPC_TASK_FLAG_DISCONNECT_CHAN);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800266 if (uipc_main.ch[i].task_evt_flags & UIPC_TASK_FLAG_DISCONNECT_CHAN)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800267 uipc_close_ch_locked(i);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800268
269 /* add here */
270
271 }
272}
273
The Android Open Source Project5738f832012-12-12 16:00:35 -0800274static int uipc_check_fd_locked(tUIPC_CH_ID ch_id)
275{
276 if (ch_id >= UIPC_CH_NUM)
277 return -1;
278
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700279 //BTIF_TRACE_EVENT("CHECK SRVFD %d (ch %d)", uipc_main.ch[ch_id].srvfd, ch_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800280
Elliott Hughes2408d9e2013-10-02 21:28:50 -0700281 if (SAFE_FD_ISSET(uipc_main.ch[ch_id].srvfd, &uipc_main.read_set))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800282 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700283 BTIF_TRACE_EVENT("INCOMING CONNECTION ON CH %d", ch_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800284
Christopher R. Palmer6dd71a52015-04-08 11:06:26 -0400285 if (uipc_main.ch[ch_id].fd > 0) {
286 BTIF_TRACE_WARNING("Channel %d has incoming connection while still connected", ch_id);
287 uipc_close_ch_locked(ch_id);
288 }
289
The Android Open Source Project5738f832012-12-12 16:00:35 -0800290 uipc_main.ch[ch_id].fd = accept_server_socket(uipc_main.ch[ch_id].srvfd);
291
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700292 BTIF_TRACE_EVENT("NEW FD %d", uipc_main.ch[ch_id].fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800293
294 if ((uipc_main.ch[ch_id].fd > 0) && uipc_main.ch[ch_id].cback)
295 {
296 /* if we have a callback we should add this fd to the active set
297 and notify user with callback event */
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700298 BTIF_TRACE_EVENT("ADD FD %d TO ACTIVE SET", uipc_main.ch[ch_id].fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800299 FD_SET(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
300 uipc_main.max_fd = MAX(uipc_main.max_fd, uipc_main.ch[ch_id].fd);
301 }
302
303 if (uipc_main.ch[ch_id].fd < 0)
304 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700305 BTIF_TRACE_ERROR("FAILED TO ACCEPT CH %d (%s)", ch_id, strerror(errno));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800306 return -1;
307 }
308
309 if (uipc_main.ch[ch_id].cback)
310 uipc_main.ch[ch_id].cback(ch_id, UIPC_OPEN_EVT);
311 }
312
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700313 //BTIF_TRACE_EVENT("CHECK FD %d (ch %d)", uipc_main.ch[ch_id].fd, ch_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800314
Elliott Hughes2408d9e2013-10-02 21:28:50 -0700315 if (SAFE_FD_ISSET(uipc_main.ch[ch_id].fd, &uipc_main.read_set))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800316 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700317 //BTIF_TRACE_EVENT("INCOMING DATA ON CH %d", ch_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800318
319 if (uipc_main.ch[ch_id].cback)
320 uipc_main.ch[ch_id].cback(ch_id, UIPC_RX_DATA_READY_EVT);
321 }
322 return 0;
323}
324
325static void uipc_check_interrupt_locked(void)
326{
Elliott Hughes2408d9e2013-10-02 21:28:50 -0700327 if (SAFE_FD_ISSET(uipc_main.signal_fds[0], &uipc_main.read_set))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800328 {
329 char sig_recv = 0;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700330 //BTIF_TRACE_EVENT("UIPC INTERRUPT");
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700331 TEMP_FAILURE_RETRY(recv(uipc_main.signal_fds[0], &sig_recv, sizeof(sig_recv), MSG_WAITALL));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800332 }
333}
334
335static inline void uipc_wakeup_locked(void)
336{
337 char sig_on = 1;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700338 BTIF_TRACE_EVENT("UIPC SEND WAKE UP");
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700339 TEMP_FAILURE_RETRY(send(uipc_main.signal_fds[1], &sig_on, sizeof(sig_on), 0));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800340}
341
342static int uipc_setup_server_locked(tUIPC_CH_ID ch_id, char *name, tUIPC_RCV_CBACK *cback)
343{
344 int fd;
345
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700346 BTIF_TRACE_EVENT("SETUP CHANNEL SERVER %d", ch_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800347
348 if (ch_id >= UIPC_CH_NUM)
349 return -1;
350
351 UIPC_LOCK();
352
353 fd = create_server_socket(name);
354
355 if (fd < 0)
356 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700357 BTIF_TRACE_ERROR("failed to setup %s", name, strerror(errno));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800358 UIPC_UNLOCK();
359 return -1;
360 }
361
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700362 BTIF_TRACE_EVENT("ADD SERVER FD TO ACTIVE SET %d", fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800363 FD_SET(fd, &uipc_main.active_set);
364 uipc_main.max_fd = MAX(uipc_main.max_fd, fd);
365
366 uipc_main.ch[ch_id].srvfd = fd;
367 uipc_main.ch[ch_id].cback = cback;
368 uipc_main.ch[ch_id].read_poll_tmo_ms = DEFAULT_READ_POLL_TMO_MS;
369
370 /* trigger main thread to update read set */
371 uipc_wakeup_locked();
372
373 UIPC_UNLOCK();
374
375 return 0;
376}
377
378static void uipc_flush_ch_locked(tUIPC_CH_ID ch_id)
379{
Bhakthavatsala Raghavendra551b9bb2014-11-21 12:24:18 -0800380 char *buf;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800381 struct pollfd pfd;
382 int ret;
Bhakthavatsala Raghavendra551b9bb2014-11-21 12:24:18 -0800383 int size = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800384
Andre Eisenbachc5916e92014-11-07 15:46:04 -0800385 pfd.events = POLLIN;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800386 pfd.fd = uipc_main.ch[ch_id].fd;
387
388 if (uipc_main.ch[ch_id].fd == UIPC_DISCONNECTED)
Andre Eisenbachc5916e92014-11-07 15:46:04 -0800389 {
390 BTIF_TRACE_EVENT("%s() - fd disconnected. Exiting", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800391 return;
Andre Eisenbachc5916e92014-11-07 15:46:04 -0800392 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800393
394 while (1)
395 {
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700396 ret = TEMP_FAILURE_RETRY(poll(&pfd, 1, 1));
Andre Eisenbachc5916e92014-11-07 15:46:04 -0800397 BTIF_TRACE_VERBOSE("%s() - polling fd %d, revents: 0x%x, ret %d",
398 __FUNCTION__, pfd.fd, pfd.revents, ret);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800399
Kim Schulzf2708dc2013-09-30 09:23:23 +0200400 if (pfd.revents & (POLLERR|POLLHUP))
Andre Eisenbachc5916e92014-11-07 15:46:04 -0800401 {
402 BTIF_TRACE_EVENT("%s() - POLLERR or POLLHUP. Exiting", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800403 return;
Bhakthavatsala Raghavendra551b9bb2014-11-21 12:24:18 -0800404 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800405
406 if (ret <= 0)
407 {
Andre Eisenbachc5916e92014-11-07 15:46:04 -0800408 BTIF_TRACE_EVENT("%s() - error (%d). Exiting", __FUNCTION__, ret);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800409 return;
410 }
Bhakthavatsala Raghavendra551b9bb2014-11-21 12:24:18 -0800411
412 ret = ioctl(uipc_main.ch[ch_id].fd, FIONREAD, &size);
413 if (ret <0) {
414 BTIF_TRACE_EVENT("uipc_flush_ch_locked: FIONREAD error: %d", ret);
415 return;
416 }
417
418 BTIF_TRACE_EVENT("uipc_flush_ch_locked: FIONREAD : %d", size);
419 buf = (char*)malloc(size);
420 if (buf == NULL) {
421 BTIF_TRACE_EVENT("uipc_flush_ch_locked: buf alloc issue %d", ret);
422 return;
423 }
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700424 ret = TEMP_FAILURE_RETRY(read(pfd.fd, buf, size));
Bhakthavatsala Raghavendra551b9bb2014-11-21 12:24:18 -0800425 BTIF_TRACE_EVENT("Flushed %d bytes", ret);
426 free(buf);
427 buf = NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800428 }
429}
430
431
432static void uipc_flush_locked(tUIPC_CH_ID ch_id)
433{
434 if (ch_id >= UIPC_CH_NUM)
435 return;
436
437 switch(ch_id)
438 {
439 case UIPC_CH_ID_AV_CTRL:
440 uipc_flush_ch_locked(UIPC_CH_ID_AV_CTRL);
441 break;
442
443 case UIPC_CH_ID_AV_AUDIO:
444 uipc_flush_ch_locked(UIPC_CH_ID_AV_AUDIO);
445 break;
446 }
447}
448
449
450static int uipc_close_ch_locked(tUIPC_CH_ID ch_id)
451{
452 int wakeup = 0;
453
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700454 BTIF_TRACE_EVENT("CLOSE CHANNEL %d", ch_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800455
456 if (ch_id >= UIPC_CH_NUM)
457 return -1;
458
Christopher R. Palmer6dd71a52015-04-08 11:06:26 -0400459 uipc_main.ch[ch_id].task_evt_flags &= ~UIPC_TASK_FLAG_DISCONNECT_CHAN;
460
The Android Open Source Project5738f832012-12-12 16:00:35 -0800461 if (uipc_main.ch[ch_id].srvfd != UIPC_DISCONNECTED)
462 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700463 BTIF_TRACE_EVENT("CLOSE SERVER (FD %d)", uipc_main.ch[ch_id].srvfd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800464 close(uipc_main.ch[ch_id].srvfd);
465 FD_CLR(uipc_main.ch[ch_id].srvfd, &uipc_main.active_set);
466 uipc_main.ch[ch_id].srvfd = UIPC_DISCONNECTED;
467 wakeup = 1;
468 }
469
470 if (uipc_main.ch[ch_id].fd != UIPC_DISCONNECTED)
471 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700472 BTIF_TRACE_EVENT("CLOSE CONNECTION (FD %d)", uipc_main.ch[ch_id].fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800473 close(uipc_main.ch[ch_id].fd);
474 FD_CLR(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
475 uipc_main.ch[ch_id].fd = UIPC_DISCONNECTED;
476 wakeup = 1;
477 }
478
479 /* notify this connection is closed */
480 if (uipc_main.ch[ch_id].cback)
481 uipc_main.ch[ch_id].cback(ch_id, UIPC_CLOSE_EVT);
482
483 /* trigger main thread update if something was updated */
484 if (wakeup)
485 uipc_wakeup_locked();
486
487 return 0;
488}
489
490
491void uipc_close_locked(tUIPC_CH_ID ch_id)
492{
493 if (uipc_main.ch[ch_id].srvfd == UIPC_DISCONNECTED)
494 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700495 BTIF_TRACE_EVENT("CHANNEL %d ALREADY CLOSED", ch_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800496 return;
497 }
498
499 /* schedule close on this channel */
500 uipc_main.ch[ch_id].task_evt_flags |= UIPC_TASK_FLAG_DISCONNECT_CHAN;
501 uipc_wakeup_locked();
502}
503
504
505static void uipc_read_task(void *arg)
506{
507 int ch_id;
508 int result;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800509 UNUSED(arg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800510
511 prctl(PR_SET_NAME, (unsigned long)"uipc-main", 0, 0, 0);
512
Mattias Agren3eae42f2014-10-02 09:43:04 +0200513 raise_priority_a2dp(TASK_UIPC_READ);
514
The Android Open Source Project5738f832012-12-12 16:00:35 -0800515 while (uipc_main.running)
516 {
517 uipc_main.read_set = uipc_main.active_set;
518
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700519 result = TEMP_FAILURE_RETRY(select(uipc_main.max_fd+1, &uipc_main.read_set, NULL, NULL, NULL));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800520
521 if (result == 0)
522 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700523 BTIF_TRACE_EVENT("select timeout");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800524 continue;
525 }
526 else if (result < 0)
527 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700528 BTIF_TRACE_EVENT("select failed %s", strerror(errno));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800529 continue;
530 }
531
532 UIPC_LOCK();
533
534 /* clear any wakeup interrupt */
535 uipc_check_interrupt_locked();
536
537 /* check pending task events */
538 uipc_check_task_flags_locked();
539
540 /* make sure we service audio channel first */
541 uipc_check_fd_locked(UIPC_CH_ID_AV_AUDIO);
542
543 /* check for other connections */
544 for (ch_id = 0; ch_id < UIPC_CH_NUM; ch_id++)
545 {
546 if (ch_id != UIPC_CH_ID_AV_AUDIO)
547 uipc_check_fd_locked(ch_id);
548 }
549
550 UIPC_UNLOCK();
551 }
552
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700553 BTIF_TRACE_EVENT("UIPC READ THREAD EXITING");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800554
555 uipc_main_cleanup();
556
557 uipc_main.tid = 0;
558
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700559 BTIF_TRACE_EVENT("UIPC READ THREAD DONE");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800560}
561
562
563int uipc_start_main_server_thread(void)
564{
565 uipc_main.running = 1;
566
567 if (pthread_create(&uipc_main.tid, (const pthread_attr_t *) NULL, (void*)uipc_read_task, NULL) < 0)
568 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700569 BTIF_TRACE_ERROR("uipc_thread_create pthread_create failed:%d", errno);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800570 return -1;
571 }
572
573 return 0;
574}
575
576/* blocking call */
577void uipc_stop_main_server_thread(void)
578{
579 /* request shutdown of read thread */
580 UIPC_LOCK();
581 uipc_main.running = 0;
582 uipc_wakeup_locked();
583 UIPC_UNLOCK();
584
585 /* wait until read thread is fully terminated */
586 if (uipc_main.tid > 0)
587 pthread_join(uipc_main.tid, NULL);
588}
589
590/*******************************************************************************
591 **
592 ** Function UIPC_Init
593 **
594 ** Description Initialize UIPC module
595 **
596 ** Returns void
597 **
598 *******************************************************************************/
599
600UDRV_API void UIPC_Init(void *p_data)
601{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800602 UNUSED(p_data);
603
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700604 BTIF_TRACE_DEBUG("UIPC_Init");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800605
606 memset(&uipc_main, 0, sizeof(tUIPC_MAIN));
607
608 uipc_main_init();
609
610 uipc_start_main_server_thread();
611}
612
613/*******************************************************************************
614 **
615 ** Function UIPC_Open
616 **
617 ** Description Open UIPC interface
618 **
619 ** Returns TRUE in case of success, FALSE in case of failure.
620 **
621 *******************************************************************************/
622UDRV_API BOOLEAN UIPC_Open(tUIPC_CH_ID ch_id, tUIPC_RCV_CBACK *p_cback)
623{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700624 BTIF_TRACE_DEBUG("UIPC_Open : ch_id %d, p_cback %x", ch_id, p_cback);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800625
626 UIPC_LOCK();
627
628 if (ch_id >= UIPC_CH_NUM)
629 {
630 UIPC_UNLOCK();
631 return FALSE;
632 }
633
634 if (uipc_main.ch[ch_id].srvfd != UIPC_DISCONNECTED)
635 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700636 BTIF_TRACE_EVENT("CHANNEL %d ALREADY OPEN", ch_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800637 UIPC_UNLOCK();
638 return 0;
639 }
640
641 switch(ch_id)
642 {
643 case UIPC_CH_ID_AV_CTRL:
644 uipc_setup_server_locked(ch_id, A2DP_CTRL_PATH, p_cback);
645 break;
646
647 case UIPC_CH_ID_AV_AUDIO:
648 uipc_setup_server_locked(ch_id, A2DP_DATA_PATH, p_cback);
649 break;
650 }
651
652 UIPC_UNLOCK();
653
654 return TRUE;
655}
656
657/*******************************************************************************
658 **
659 ** Function UIPC_Close
660 **
661 ** Description Close UIPC interface
662 **
663 ** Returns void
664 **
665 *******************************************************************************/
666
667UDRV_API void UIPC_Close(tUIPC_CH_ID ch_id)
668{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700669 BTIF_TRACE_DEBUG("UIPC_Close : ch_id %d", ch_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800670
671 /* special case handling uipc shutdown */
672 if (ch_id != UIPC_CH_ID_ALL)
673 {
674 UIPC_LOCK();
675 uipc_close_locked(ch_id);
676 UIPC_UNLOCK();
677 }
678 else
679 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700680 BTIF_TRACE_DEBUG("UIPC_Close : waiting for shutdown to complete");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800681 uipc_stop_main_server_thread();
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700682 BTIF_TRACE_DEBUG("UIPC_Close : shutdown complete");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800683 }
684}
685
686/*******************************************************************************
687 **
688 ** Function UIPC_SendBuf
689 **
690 ** Description Called to transmit a message over UIPC.
691 ** Message buffer will be freed by UIPC_SendBuf.
692 **
693 ** Returns TRUE in case of success, FALSE in case of failure.
694 **
695 *******************************************************************************/
696UDRV_API BOOLEAN UIPC_SendBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg)
697{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800698 UNUSED(p_msg);
699
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700700 BTIF_TRACE_DEBUG("UIPC_SendBuf : ch_id %d NOT IMPLEMENTED", ch_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800701
702 UIPC_LOCK();
703
704 /* currently not used */
705
706 UIPC_UNLOCK();
707
708 return FALSE;
709}
710
711/*******************************************************************************
712 **
713 ** Function UIPC_Send
714 **
715 ** Description Called to transmit a message over UIPC.
716 **
717 ** Returns TRUE in case of success, FALSE in case of failure.
718 **
719 *******************************************************************************/
720UDRV_API BOOLEAN UIPC_Send(tUIPC_CH_ID ch_id, UINT16 msg_evt, UINT8 *p_buf,
721 UINT16 msglen)
722{
723 int n;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800724 UNUSED(msg_evt);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800725
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700726 BTIF_TRACE_DEBUG("UIPC_Send : ch_id:%d %d bytes", ch_id, msglen);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800727
728 UIPC_LOCK();
729
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700730 if (TEMP_FAILURE_RETRY(write(uipc_main.ch[ch_id].fd, p_buf, msglen)) < 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800731 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700732 BTIF_TRACE_ERROR("failed to write (%s)", strerror(errno));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800733 }
734
735 UIPC_UNLOCK();
736
737 return FALSE;
738}
739
740/*******************************************************************************
741 **
742 ** Function UIPC_ReadBuf
743 **
744 ** Description Called to read a message from UIPC.
745 **
746 ** Returns void
747 **
748 *******************************************************************************/
749UDRV_API void UIPC_ReadBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg)
750{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800751 UNUSED(p_msg);
752
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700753 BTIF_TRACE_DEBUG("UIPC_ReadBuf : ch_id:%d NOT IMPLEMENTED", ch_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800754
755 UIPC_LOCK();
756 UIPC_UNLOCK();
757}
758
759/*******************************************************************************
760 **
761 ** Function UIPC_Read
762 **
763 ** Description Called to read a message from UIPC.
764 **
765 ** Returns return the number of bytes read.
766 **
767 *******************************************************************************/
768
769UDRV_API UINT32 UIPC_Read(tUIPC_CH_ID ch_id, UINT16 *p_msg_evt, UINT8 *p_buf, UINT32 len)
770{
771 int n;
772 int n_read = 0;
773 int fd = uipc_main.ch[ch_id].fd;
774 struct pollfd pfd;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800775 UNUSED(p_msg_evt);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800776
777 if (ch_id >= UIPC_CH_NUM)
778 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700779 BTIF_TRACE_ERROR("UIPC_Read : invalid ch id %d", ch_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800780 return 0;
781 }
782
783 if (fd == UIPC_DISCONNECTED)
784 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700785 BTIF_TRACE_ERROR("UIPC_Read : channel %d closed", ch_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800786 return 0;
787 }
788
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700789 //BTIF_TRACE_DEBUG("UIPC_Read : ch_id %d, len %d, fd %d, polltmo %d", ch_id, len,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800790 // fd, uipc_main.ch[ch_id].read_poll_tmo_ms);
791
792 while (n_read < (int)len)
793 {
794 pfd.fd = fd;
795 pfd.events = POLLIN|POLLHUP;
796
797 /* make sure there is data prior to attempting read to avoid blocking
798 a read for more than poll timeout */
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700799 if (TEMP_FAILURE_RETRY(poll(&pfd, 1, uipc_main.ch[ch_id].read_poll_tmo_ms)) == 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800800 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700801 BTIF_TRACE_EVENT("poll timeout (%d ms)", uipc_main.ch[ch_id].read_poll_tmo_ms);
Zhihai Xu01c686c2013-09-15 19:59:37 -0700802 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800803 }
804
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700805 //BTIF_TRACE_EVENT("poll revents %x", pfd.revents);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800806
807 if (pfd.revents & (POLLHUP|POLLNVAL) )
808 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700809 BTIF_TRACE_EVENT("poll : channel detached remotely");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800810 UIPC_LOCK();
811 uipc_close_locked(ch_id);
812 UIPC_UNLOCK();
813 return 0;
814 }
815
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700816 n = TEMP_FAILURE_RETRY(recv(fd, p_buf+n_read, len-n_read, 0));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800817
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700818 //BTIF_TRACE_EVENT("read %d bytes", n);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800819
820 if (n == 0)
821 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700822 BTIF_TRACE_EVENT("UIPC_Read : channel detached remotely");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800823 UIPC_LOCK();
824 uipc_close_locked(ch_id);
825 UIPC_UNLOCK();
826 return 0;
827 }
828
829 if (n < 0)
830 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700831 BTIF_TRACE_EVENT("UIPC_Read : read failed (%s)", strerror(errno));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800832 return 0;
833 }
834
835 n_read+=n;
836
837 }
838
839 return n_read;
840}
841
842/*******************************************************************************
843**
844** Function UIPC_Ioctl
845**
846** Description Called to control UIPC.
847**
848** Returns void
849**
850*******************************************************************************/
851
852UDRV_API extern BOOLEAN UIPC_Ioctl(tUIPC_CH_ID ch_id, UINT32 request, void *param)
853{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700854 BTIF_TRACE_DEBUG("#### UIPC_Ioctl : ch_id %d, request %d ####", ch_id, request);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800855
856 UIPC_LOCK();
857
858 switch(request)
859 {
860 case UIPC_REQ_RX_FLUSH:
861 uipc_flush_locked(ch_id);
862 break;
863
864 case UIPC_REG_CBACK:
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700865 //BTIF_TRACE_EVENT("register callback ch %d srvfd %d, fd %d", ch_id, uipc_main.ch[ch_id].srvfd, uipc_main.ch[ch_id].fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800866 uipc_main.ch[ch_id].cback = (tUIPC_RCV_CBACK*)param;
867 break;
868
869 case UIPC_REG_REMOVE_ACTIVE_READSET:
870
871 /* user will read data directly and not use select loop */
872 if (uipc_main.ch[ch_id].fd != UIPC_DISCONNECTED)
873 {
874 /* remove this channel from active set */
875 FD_CLR(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
876
877 /* refresh active set */
878 uipc_wakeup_locked();
879 }
880 break;
881
882 case UIPC_SET_READ_POLL_TMO:
Kévin PETIT22c6e502014-02-12 17:24:01 +0000883 uipc_main.ch[ch_id].read_poll_tmo_ms = (intptr_t)param;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700884 BTIF_TRACE_EVENT("UIPC_SET_READ_POLL_TMO : CH %d, TMO %d ms", ch_id, uipc_main.ch[ch_id].read_poll_tmo_ms );
The Android Open Source Project5738f832012-12-12 16:00:35 -0800885 break;
886
887 default:
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700888 BTIF_TRACE_EVENT("UIPC_Ioctl : request not handled (%d)", request);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800889 break;
890 }
891
892 UIPC_UNLOCK();
893
894 return FALSE;
895}