The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 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: 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 Raghavendra | 551b9bb | 2014-11-21 12:24:18 -0800 | [diff] [blame] | 37 | #include <sys/ioctl.h> |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 38 | #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. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 54 | #include "bt_utils.h" |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 55 | |
| 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 Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 68 | #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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 70 | |
Elliott Hughes | 2408d9e | 2013-10-02 21:28:50 -0700 | [diff] [blame] | 71 | #define SAFE_FD_ISSET(fd, set) (((fd) == -1) ? FALSE : FD_ISSET((fd), (set))) |
| 72 | |
Andre Eisenbach | c5916e9 | 2014-11-07 15:46:04 -0800 | [diff] [blame] | 73 | #define UIPC_FLUSH_BUFFER_SIZE 1024 |
| 74 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 75 | /***************************************************************************** |
| 76 | ** Local type definitions |
| 77 | ******************************************************************************/ |
| 78 | |
| 79 | typedef enum { |
| 80 | UIPC_TASK_FLAG_DISCONNECT_CHAN = 0x1, |
| 81 | } tUIPC_TASK_FLAGS; |
| 82 | |
| 83 | typedef 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 | |
| 94 | typedef 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 | |
| 112 | static tUIPC_MAIN uipc_main; |
| 113 | |
| 114 | |
| 115 | /***************************************************************************** |
| 116 | ** Static functions |
| 117 | ******************************************************************************/ |
| 118 | |
| 119 | static int uipc_close_ch_locked(tUIPC_CH_ID ch_id); |
| 120 | |
| 121 | /***************************************************************************** |
| 122 | ** Externs |
| 123 | ******************************************************************************/ |
| 124 | |
| 125 | |
| 126 | /***************************************************************************** |
| 127 | ** Helper functions |
| 128 | ******************************************************************************/ |
| 129 | |
| 130 | |
| 131 | const 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 146 | ** socket helper functions |
| 147 | *****************************************************************************/ |
| 148 | |
| 149 | static inline int create_server_socket(const char* name) |
| 150 | { |
| 151 | int s = socket(AF_LOCAL, SOCK_STREAM, 0); |
| 152 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 153 | BTIF_TRACE_EVENT("create_server_socket %s", name); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 154 | |
| 155 | if(socket_local_server_bind(s, name, ANDROID_SOCKET_NAMESPACE_ABSTRACT) < 0) |
| 156 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 157 | BTIF_TRACE_EVENT("socket failed to create (%s)", strerror(errno)); |
Kim Schulz | 2a2701c | 2013-09-16 15:59:33 +0200 | [diff] [blame] | 158 | close(s); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 159 | return -1; |
| 160 | } |
| 161 | |
| 162 | if(listen(s, 5) < 0) |
| 163 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 164 | BTIF_TRACE_EVENT("listen failed", strerror(errno)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 165 | close(s); |
| 166 | return -1; |
| 167 | } |
| 168 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 169 | BTIF_TRACE_EVENT("created socket fd %d", s); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 170 | return s; |
| 171 | } |
| 172 | |
| 173 | static int accept_server_socket(int sfd) |
| 174 | { |
| 175 | struct sockaddr_un remote; |
| 176 | struct pollfd pfd; |
| 177 | int fd; |
Elliott Hughes | 730a4b2 | 2014-02-07 12:23:05 -0800 | [diff] [blame] | 178 | socklen_t len = sizeof(struct sockaddr_un); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 179 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 180 | BTIF_TRACE_EVENT("accept fd %d", sfd); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 181 | |
| 182 | /* make sure there is data to process */ |
| 183 | pfd.fd = sfd; |
| 184 | pfd.events = POLLIN; |
| 185 | |
Sharvil Nanavati | 405b5c9 | 2016-06-17 14:15:46 -0700 | [diff] [blame] | 186 | if (TEMP_FAILURE_RETRY(poll(&pfd, 1, 0)) == 0) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 187 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 188 | BTIF_TRACE_EVENT("accept poll timeout"); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 189 | return -1; |
| 190 | } |
| 191 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 192 | //BTIF_TRACE_EVENT("poll revents 0x%x", pfd.revents); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 193 | |
Sharvil Nanavati | 405b5c9 | 2016-06-17 14:15:46 -0700 | [diff] [blame] | 194 | if ((fd = TEMP_FAILURE_RETRY(accept(sfd, (struct sockaddr *)&remote, &len))) == -1) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 195 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 196 | BTIF_TRACE_ERROR("sock accept failed (%s)", strerror(errno)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 197 | return -1; |
| 198 | } |
| 199 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 200 | //BTIF_TRACE_EVENT("new fd %d", fd); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 201 | |
| 202 | return fd; |
| 203 | } |
| 204 | |
| 205 | /***************************************************************************** |
| 206 | ** |
| 207 | ** uipc helper functions |
| 208 | ** |
| 209 | *****************************************************************************/ |
| 210 | |
| 211 | static 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 Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 217 | BTIF_TRACE_EVENT("### uipc_main_init ###"); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 218 | |
| 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 | |
| 242 | void uipc_main_cleanup(void) |
| 243 | { |
| 244 | int i; |
| 245 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 246 | BTIF_TRACE_EVENT("uipc_main_cleanup"); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 247 | |
| 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 */ |
| 259 | static void uipc_check_task_flags_locked(void) |
| 260 | { |
| 261 | int i; |
| 262 | |
| 263 | for (i=0; i<UIPC_CH_NUM; i++) |
| 264 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 265 | //BTIF_TRACE_EVENT("CHECK TASK FLAGS %x %x", uipc_main.ch[i].task_evt_flags, UIPC_TASK_FLAG_DISCONNECT_CHAN); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 266 | if (uipc_main.ch[i].task_evt_flags & UIPC_TASK_FLAG_DISCONNECT_CHAN) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 267 | uipc_close_ch_locked(i); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 268 | |
| 269 | /* add here */ |
| 270 | |
| 271 | } |
| 272 | } |
| 273 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 274 | static int uipc_check_fd_locked(tUIPC_CH_ID ch_id) |
| 275 | { |
| 276 | if (ch_id >= UIPC_CH_NUM) |
| 277 | return -1; |
| 278 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 279 | //BTIF_TRACE_EVENT("CHECK SRVFD %d (ch %d)", uipc_main.ch[ch_id].srvfd, ch_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 280 | |
Elliott Hughes | 2408d9e | 2013-10-02 21:28:50 -0700 | [diff] [blame] | 281 | if (SAFE_FD_ISSET(uipc_main.ch[ch_id].srvfd, &uipc_main.read_set)) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 282 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 283 | BTIF_TRACE_EVENT("INCOMING CONNECTION ON CH %d", ch_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 284 | |
Christopher R. Palmer | 6dd71a5 | 2015-04-08 11:06:26 -0400 | [diff] [blame] | 285 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 290 | uipc_main.ch[ch_id].fd = accept_server_socket(uipc_main.ch[ch_id].srvfd); |
| 291 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 292 | BTIF_TRACE_EVENT("NEW FD %d", uipc_main.ch[ch_id].fd); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 293 | |
| 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 Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 298 | BTIF_TRACE_EVENT("ADD FD %d TO ACTIVE SET", uipc_main.ch[ch_id].fd); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 299 | 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 Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 305 | BTIF_TRACE_ERROR("FAILED TO ACCEPT CH %d (%s)", ch_id, strerror(errno)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 306 | 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 Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 313 | //BTIF_TRACE_EVENT("CHECK FD %d (ch %d)", uipc_main.ch[ch_id].fd, ch_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 314 | |
Elliott Hughes | 2408d9e | 2013-10-02 21:28:50 -0700 | [diff] [blame] | 315 | if (SAFE_FD_ISSET(uipc_main.ch[ch_id].fd, &uipc_main.read_set)) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 316 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 317 | //BTIF_TRACE_EVENT("INCOMING DATA ON CH %d", ch_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 318 | |
| 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 | |
| 325 | static void uipc_check_interrupt_locked(void) |
| 326 | { |
Elliott Hughes | 2408d9e | 2013-10-02 21:28:50 -0700 | [diff] [blame] | 327 | if (SAFE_FD_ISSET(uipc_main.signal_fds[0], &uipc_main.read_set)) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 328 | { |
| 329 | char sig_recv = 0; |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 330 | //BTIF_TRACE_EVENT("UIPC INTERRUPT"); |
Sharvil Nanavati | 405b5c9 | 2016-06-17 14:15:46 -0700 | [diff] [blame] | 331 | TEMP_FAILURE_RETRY(recv(uipc_main.signal_fds[0], &sig_recv, sizeof(sig_recv), MSG_WAITALL)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 332 | } |
| 333 | } |
| 334 | |
| 335 | static inline void uipc_wakeup_locked(void) |
| 336 | { |
| 337 | char sig_on = 1; |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 338 | BTIF_TRACE_EVENT("UIPC SEND WAKE UP"); |
Sharvil Nanavati | 405b5c9 | 2016-06-17 14:15:46 -0700 | [diff] [blame] | 339 | TEMP_FAILURE_RETRY(send(uipc_main.signal_fds[1], &sig_on, sizeof(sig_on), 0)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 340 | } |
| 341 | |
| 342 | static int uipc_setup_server_locked(tUIPC_CH_ID ch_id, char *name, tUIPC_RCV_CBACK *cback) |
| 343 | { |
| 344 | int fd; |
| 345 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 346 | BTIF_TRACE_EVENT("SETUP CHANNEL SERVER %d", ch_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 347 | |
| 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 Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 357 | BTIF_TRACE_ERROR("failed to setup %s", name, strerror(errno)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 358 | UIPC_UNLOCK(); |
| 359 | return -1; |
| 360 | } |
| 361 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 362 | BTIF_TRACE_EVENT("ADD SERVER FD TO ACTIVE SET %d", fd); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 363 | 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 | |
| 378 | static void uipc_flush_ch_locked(tUIPC_CH_ID ch_id) |
| 379 | { |
Bhakthavatsala Raghavendra | 551b9bb | 2014-11-21 12:24:18 -0800 | [diff] [blame] | 380 | char *buf; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 381 | struct pollfd pfd; |
| 382 | int ret; |
Bhakthavatsala Raghavendra | 551b9bb | 2014-11-21 12:24:18 -0800 | [diff] [blame] | 383 | int size = 0; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 384 | |
Andre Eisenbach | c5916e9 | 2014-11-07 15:46:04 -0800 | [diff] [blame] | 385 | pfd.events = POLLIN; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 386 | pfd.fd = uipc_main.ch[ch_id].fd; |
| 387 | |
| 388 | if (uipc_main.ch[ch_id].fd == UIPC_DISCONNECTED) |
Andre Eisenbach | c5916e9 | 2014-11-07 15:46:04 -0800 | [diff] [blame] | 389 | { |
| 390 | BTIF_TRACE_EVENT("%s() - fd disconnected. Exiting", __FUNCTION__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 391 | return; |
Andre Eisenbach | c5916e9 | 2014-11-07 15:46:04 -0800 | [diff] [blame] | 392 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 393 | |
| 394 | while (1) |
| 395 | { |
Sharvil Nanavati | 405b5c9 | 2016-06-17 14:15:46 -0700 | [diff] [blame] | 396 | ret = TEMP_FAILURE_RETRY(poll(&pfd, 1, 1)); |
Andre Eisenbach | c5916e9 | 2014-11-07 15:46:04 -0800 | [diff] [blame] | 397 | BTIF_TRACE_VERBOSE("%s() - polling fd %d, revents: 0x%x, ret %d", |
| 398 | __FUNCTION__, pfd.fd, pfd.revents, ret); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 399 | |
Kim Schulz | f2708dc | 2013-09-30 09:23:23 +0200 | [diff] [blame] | 400 | if (pfd.revents & (POLLERR|POLLHUP)) |
Andre Eisenbach | c5916e9 | 2014-11-07 15:46:04 -0800 | [diff] [blame] | 401 | { |
| 402 | BTIF_TRACE_EVENT("%s() - POLLERR or POLLHUP. Exiting", __FUNCTION__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 403 | return; |
Bhakthavatsala Raghavendra | 551b9bb | 2014-11-21 12:24:18 -0800 | [diff] [blame] | 404 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 405 | |
| 406 | if (ret <= 0) |
| 407 | { |
Andre Eisenbach | c5916e9 | 2014-11-07 15:46:04 -0800 | [diff] [blame] | 408 | BTIF_TRACE_EVENT("%s() - error (%d). Exiting", __FUNCTION__, ret); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 409 | return; |
| 410 | } |
Bhakthavatsala Raghavendra | 551b9bb | 2014-11-21 12:24:18 -0800 | [diff] [blame] | 411 | |
| 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 Nanavati | 405b5c9 | 2016-06-17 14:15:46 -0700 | [diff] [blame] | 424 | ret = TEMP_FAILURE_RETRY(read(pfd.fd, buf, size)); |
Bhakthavatsala Raghavendra | 551b9bb | 2014-11-21 12:24:18 -0800 | [diff] [blame] | 425 | BTIF_TRACE_EVENT("Flushed %d bytes", ret); |
| 426 | free(buf); |
| 427 | buf = NULL; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 428 | } |
| 429 | } |
| 430 | |
| 431 | |
| 432 | static 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 | |
| 450 | static int uipc_close_ch_locked(tUIPC_CH_ID ch_id) |
| 451 | { |
| 452 | int wakeup = 0; |
| 453 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 454 | BTIF_TRACE_EVENT("CLOSE CHANNEL %d", ch_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 455 | |
| 456 | if (ch_id >= UIPC_CH_NUM) |
| 457 | return -1; |
| 458 | |
Christopher R. Palmer | 6dd71a5 | 2015-04-08 11:06:26 -0400 | [diff] [blame] | 459 | uipc_main.ch[ch_id].task_evt_flags &= ~UIPC_TASK_FLAG_DISCONNECT_CHAN; |
| 460 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 461 | if (uipc_main.ch[ch_id].srvfd != UIPC_DISCONNECTED) |
| 462 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 463 | BTIF_TRACE_EVENT("CLOSE SERVER (FD %d)", uipc_main.ch[ch_id].srvfd); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 464 | 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 Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 472 | BTIF_TRACE_EVENT("CLOSE CONNECTION (FD %d)", uipc_main.ch[ch_id].fd); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 473 | 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 | |
| 491 | void uipc_close_locked(tUIPC_CH_ID ch_id) |
| 492 | { |
| 493 | if (uipc_main.ch[ch_id].srvfd == UIPC_DISCONNECTED) |
| 494 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 495 | BTIF_TRACE_EVENT("CHANNEL %d ALREADY CLOSED", ch_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 496 | 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 | |
| 505 | static void uipc_read_task(void *arg) |
| 506 | { |
| 507 | int ch_id; |
| 508 | int result; |
Mike J. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 509 | UNUSED(arg); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 510 | |
| 511 | prctl(PR_SET_NAME, (unsigned long)"uipc-main", 0, 0, 0); |
| 512 | |
Mattias Agren | 3eae42f | 2014-10-02 09:43:04 +0200 | [diff] [blame] | 513 | raise_priority_a2dp(TASK_UIPC_READ); |
| 514 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 515 | while (uipc_main.running) |
| 516 | { |
| 517 | uipc_main.read_set = uipc_main.active_set; |
| 518 | |
Sharvil Nanavati | 405b5c9 | 2016-06-17 14:15:46 -0700 | [diff] [blame] | 519 | result = TEMP_FAILURE_RETRY(select(uipc_main.max_fd+1, &uipc_main.read_set, NULL, NULL, NULL)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 520 | |
| 521 | if (result == 0) |
| 522 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 523 | BTIF_TRACE_EVENT("select timeout"); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 524 | continue; |
| 525 | } |
| 526 | else if (result < 0) |
| 527 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 528 | BTIF_TRACE_EVENT("select failed %s", strerror(errno)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 529 | 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 Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 553 | BTIF_TRACE_EVENT("UIPC READ THREAD EXITING"); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 554 | |
| 555 | uipc_main_cleanup(); |
| 556 | |
| 557 | uipc_main.tid = 0; |
| 558 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 559 | BTIF_TRACE_EVENT("UIPC READ THREAD DONE"); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 560 | } |
| 561 | |
| 562 | |
| 563 | int 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 Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 569 | BTIF_TRACE_ERROR("uipc_thread_create pthread_create failed:%d", errno); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 570 | return -1; |
| 571 | } |
| 572 | |
| 573 | return 0; |
| 574 | } |
| 575 | |
| 576 | /* blocking call */ |
| 577 | void 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 | |
| 600 | UDRV_API void UIPC_Init(void *p_data) |
| 601 | { |
Mike J. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 602 | UNUSED(p_data); |
| 603 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 604 | BTIF_TRACE_DEBUG("UIPC_Init"); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 605 | |
| 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 | *******************************************************************************/ |
| 622 | UDRV_API BOOLEAN UIPC_Open(tUIPC_CH_ID ch_id, tUIPC_RCV_CBACK *p_cback) |
| 623 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 624 | BTIF_TRACE_DEBUG("UIPC_Open : ch_id %d, p_cback %x", ch_id, p_cback); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 625 | |
| 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 Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 636 | BTIF_TRACE_EVENT("CHANNEL %d ALREADY OPEN", ch_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 637 | 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 | |
| 667 | UDRV_API void UIPC_Close(tUIPC_CH_ID ch_id) |
| 668 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 669 | BTIF_TRACE_DEBUG("UIPC_Close : ch_id %d", ch_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 670 | |
| 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 Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 680 | BTIF_TRACE_DEBUG("UIPC_Close : waiting for shutdown to complete"); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 681 | uipc_stop_main_server_thread(); |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 682 | BTIF_TRACE_DEBUG("UIPC_Close : shutdown complete"); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 683 | } |
| 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 | *******************************************************************************/ |
| 696 | UDRV_API BOOLEAN UIPC_SendBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg) |
| 697 | { |
Mike J. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 698 | UNUSED(p_msg); |
| 699 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 700 | BTIF_TRACE_DEBUG("UIPC_SendBuf : ch_id %d NOT IMPLEMENTED", ch_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 701 | |
| 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 | *******************************************************************************/ |
| 720 | UDRV_API BOOLEAN UIPC_Send(tUIPC_CH_ID ch_id, UINT16 msg_evt, UINT8 *p_buf, |
| 721 | UINT16 msglen) |
| 722 | { |
| 723 | int n; |
Mike J. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 724 | UNUSED(msg_evt); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 725 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 726 | BTIF_TRACE_DEBUG("UIPC_Send : ch_id:%d %d bytes", ch_id, msglen); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 727 | |
| 728 | UIPC_LOCK(); |
| 729 | |
Sharvil Nanavati | 405b5c9 | 2016-06-17 14:15:46 -0700 | [diff] [blame] | 730 | if (TEMP_FAILURE_RETRY(write(uipc_main.ch[ch_id].fd, p_buf, msglen)) < 0) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 731 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 732 | BTIF_TRACE_ERROR("failed to write (%s)", strerror(errno)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 733 | } |
| 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 | *******************************************************************************/ |
| 749 | UDRV_API void UIPC_ReadBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg) |
| 750 | { |
Mike J. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 751 | UNUSED(p_msg); |
| 752 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 753 | BTIF_TRACE_DEBUG("UIPC_ReadBuf : ch_id:%d NOT IMPLEMENTED", ch_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 754 | |
| 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 | |
| 769 | UDRV_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. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 775 | UNUSED(p_msg_evt); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 776 | |
| 777 | if (ch_id >= UIPC_CH_NUM) |
| 778 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 779 | BTIF_TRACE_ERROR("UIPC_Read : invalid ch id %d", ch_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 780 | return 0; |
| 781 | } |
| 782 | |
| 783 | if (fd == UIPC_DISCONNECTED) |
| 784 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 785 | BTIF_TRACE_ERROR("UIPC_Read : channel %d closed", ch_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 786 | return 0; |
| 787 | } |
| 788 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 789 | //BTIF_TRACE_DEBUG("UIPC_Read : ch_id %d, len %d, fd %d, polltmo %d", ch_id, len, |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 790 | // 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 Nanavati | 405b5c9 | 2016-06-17 14:15:46 -0700 | [diff] [blame] | 799 | if (TEMP_FAILURE_RETRY(poll(&pfd, 1, uipc_main.ch[ch_id].read_poll_tmo_ms)) == 0) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 800 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 801 | BTIF_TRACE_EVENT("poll timeout (%d ms)", uipc_main.ch[ch_id].read_poll_tmo_ms); |
Zhihai Xu | 01c686c | 2013-09-15 19:59:37 -0700 | [diff] [blame] | 802 | break; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 803 | } |
| 804 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 805 | //BTIF_TRACE_EVENT("poll revents %x", pfd.revents); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 806 | |
| 807 | if (pfd.revents & (POLLHUP|POLLNVAL) ) |
| 808 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 809 | BTIF_TRACE_EVENT("poll : channel detached remotely"); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 810 | UIPC_LOCK(); |
| 811 | uipc_close_locked(ch_id); |
| 812 | UIPC_UNLOCK(); |
| 813 | return 0; |
| 814 | } |
| 815 | |
Sharvil Nanavati | 405b5c9 | 2016-06-17 14:15:46 -0700 | [diff] [blame] | 816 | n = TEMP_FAILURE_RETRY(recv(fd, p_buf+n_read, len-n_read, 0)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 817 | |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 818 | //BTIF_TRACE_EVENT("read %d bytes", n); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 819 | |
| 820 | if (n == 0) |
| 821 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 822 | BTIF_TRACE_EVENT("UIPC_Read : channel detached remotely"); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 823 | UIPC_LOCK(); |
| 824 | uipc_close_locked(ch_id); |
| 825 | UIPC_UNLOCK(); |
| 826 | return 0; |
| 827 | } |
| 828 | |
| 829 | if (n < 0) |
| 830 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 831 | BTIF_TRACE_EVENT("UIPC_Read : read failed (%s)", strerror(errno)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 832 | 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 | |
| 852 | UDRV_API extern BOOLEAN UIPC_Ioctl(tUIPC_CH_ID ch_id, UINT32 request, void *param) |
| 853 | { |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 854 | BTIF_TRACE_DEBUG("#### UIPC_Ioctl : ch_id %d, request %d ####", ch_id, request); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 855 | |
| 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 Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 865 | //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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 866 | 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 PETIT | 22c6e50 | 2014-02-12 17:24:01 +0000 | [diff] [blame] | 883 | uipc_main.ch[ch_id].read_poll_tmo_ms = (intptr_t)param; |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 884 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 885 | break; |
| 886 | |
| 887 | default: |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 888 | BTIF_TRACE_EVENT("UIPC_Ioctl : request not handled (%d)", request); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 889 | break; |
| 890 | } |
| 891 | |
| 892 | UIPC_UNLOCK(); |
| 893 | |
| 894 | return FALSE; |
| 895 | } |