1 /******************************************************************************
2 *
3 * Copyright 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.cc
22 *
23 * Description: UIPC implementation for fluoride
24 *
25 *****************************************************************************/
26
27 #define LOG_TAG "uipc"
28
29 #include "udrv/include/uipc.h"
30
31 #include <bluetooth/log.h>
32 #include <fcntl.h>
33 #include <poll.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/mman.h>
37 #include <sys/prctl.h>
38 #include <sys/select.h>
39 #include <sys/socket.h>
40 #include <sys/stat.h>
41 #include <sys/un.h>
42 #include <unistd.h>
43
44 #include <cerrno>
45 #include <mutex>
46
47 #include "osi/include/osi.h"
48 #include "osi/include/socket_utils/sockets.h"
49
50 using namespace bluetooth;
51
52 /*****************************************************************************
53 * Constants & Macros
54 *****************************************************************************/
55
56 // AUDIO_STREAM_OUTPUT_BUFFER_SZ controls the size of the audio socket buffer.
57 // If one assumes the write buffer is always full during normal BT playback,
58 // then increasing this value increases our playback latency.
59 //
60 // FIXME: The BT HAL should consume data at a constant rate.
61 // AudioFlinger assumes that the HAL draws data at a constant rate, which is
62 // true for most audio devices; however, the BT engine reads data at a variable
63 // rate (over the short term), which confuses both AudioFlinger as well as
64 // applications which deliver data at a (generally) fixed rate.
65 //
66 // 20 * 512 is not sufficient to smooth the variability for some BT devices,
67 // resulting in mixer sleep and throttling. We increase this to 28 * 512 to help
68 // reduce the effect of variable data consumption.
69 #define AUDIO_STREAM_OUTPUT_BUFFER_SZ (28 * 512)
70
71 #define MAX(a, b) ((a) > (b) ? (a) : (b))
72
73 #define CASE_RETURN_STR(const) \
74 case const: \
75 return #const;
76
77 #define UIPC_DISCONNECTED (-1)
78
79 #define SAFE_FD_ISSET(fd, set) (((fd) == -1) ? false : FD_ISSET((fd), (set)))
80
81 #define UIPC_FLUSH_BUFFER_SIZE 1024
82
83 /*****************************************************************************
84 * Local type definitions
85 *****************************************************************************/
86
87 typedef enum {
88 UIPC_TASK_FLAG_DISCONNECT_CHAN = 0x1,
89 } tUIPC_TASK_FLAGS;
90
91 /*****************************************************************************
92 * Static functions
93 *****************************************************************************/
94 static int uipc_close_ch_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id);
95
96 /*****************************************************************************
97 * Externs
98 *****************************************************************************/
99
100 /*****************************************************************************
101 * Helper functions
102 *****************************************************************************/
103
dump_uipc_event(tUIPC_EVENT event)104 const char* dump_uipc_event(tUIPC_EVENT event) {
105 switch (event) {
106 CASE_RETURN_STR(UIPC_OPEN_EVT)
107 CASE_RETURN_STR(UIPC_CLOSE_EVT)
108 CASE_RETURN_STR(UIPC_RX_DATA_EVT)
109 CASE_RETURN_STR(UIPC_RX_DATA_READY_EVT)
110 CASE_RETURN_STR(UIPC_TX_DATA_READY_EVT)
111 default:
112 return "UNKNOWN MSG ID";
113 }
114 }
115
116 /*****************************************************************************
117 * socket helper functions
118 ****************************************************************************/
119
create_server_socket(const char * name)120 static inline int create_server_socket(const char* name) {
121 int s = socket(AF_LOCAL, SOCK_STREAM, 0);
122 if (s < 0) {
123 return -1;
124 }
125
126 log::debug("create_server_socket {}", name);
127
128 if (osi_socket_local_server_bind(s, name,
129 #ifdef __ANDROID__
130 ANDROID_SOCKET_NAMESPACE_ABSTRACT
131 #else // !__ANDROID__
132 ANDROID_SOCKET_NAMESPACE_FILESYSTEM
133 #endif // __ANDROID__
134 ) < 0) {
135 log::debug("socket failed to create ({})", strerror(errno));
136 close(s);
137 return -1;
138 }
139
140 if (listen(s, 5) < 0) {
141 log::debug("listen failed: {}", strerror(errno));
142 close(s);
143 return -1;
144 }
145
146 log::debug("created socket fd {}", s);
147 return s;
148 }
149
accept_server_socket(int sfd)150 static int accept_server_socket(int sfd) {
151 struct sockaddr_un remote;
152 struct pollfd pfd;
153 int fd;
154 socklen_t len = sizeof(struct sockaddr_un);
155
156 log::debug("accept fd {}", sfd);
157
158 /* make sure there is data to process */
159 pfd.fd = sfd;
160 pfd.events = POLLIN;
161
162 int poll_ret;
163 OSI_NO_INTR(poll_ret = poll(&pfd, 1, 0));
164 if (poll_ret == 0) {
165 log::warn("accept poll timeout");
166 return -1;
167 }
168
169 OSI_NO_INTR(fd = accept(sfd, (struct sockaddr*)&remote, &len));
170 if (fd == -1) {
171 log::error("sock accept failed ({})", strerror(errno));
172 return -1;
173 }
174
175 // match socket buffer size option with client
176 const int size = AUDIO_STREAM_OUTPUT_BUFFER_SZ;
177 int ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&size, (int)sizeof(size));
178 if (ret < 0) {
179 log::error("setsockopt failed ({})", strerror(errno));
180 }
181
182 return fd;
183 }
184
185 /*****************************************************************************
186 *
187 * uipc helper functions
188 *
189 ****************************************************************************/
190
uipc_main_init(tUIPC_STATE & uipc)191 static int uipc_main_init(tUIPC_STATE& uipc) {
192 int i;
193
194 log::debug("### uipc_main_init ###");
195
196 uipc.tid = 0;
197 uipc.running = 0;
198 memset(&uipc.active_set, 0, sizeof(uipc.active_set));
199 memset(&uipc.read_set, 0, sizeof(uipc.read_set));
200 uipc.max_fd = 0;
201 memset(&uipc.signal_fds, 0, sizeof(uipc.signal_fds));
202 memset(&uipc.ch, 0, sizeof(uipc.ch));
203
204 /* setup interrupt socket pair */
205 if (socketpair(AF_UNIX, SOCK_STREAM, 0, uipc.signal_fds) < 0) {
206 return -1;
207 }
208
209 FD_SET(uipc.signal_fds[0], &uipc.active_set);
210 uipc.max_fd = MAX(uipc.max_fd, uipc.signal_fds[0]);
211
212 for (i = 0; i < UIPC_CH_NUM; i++) {
213 tUIPC_CHAN* p = &uipc.ch[i];
214 p->srvfd = UIPC_DISCONNECTED;
215 p->fd = UIPC_DISCONNECTED;
216 p->task_evt_flags = 0;
217 p->cback = NULL;
218 }
219
220 return 0;
221 }
222
uipc_main_cleanup(tUIPC_STATE & uipc)223 static void uipc_main_cleanup(tUIPC_STATE& uipc) {
224 int i;
225
226 log::debug("uipc_main_cleanup");
227
228 close(uipc.signal_fds[0]);
229 close(uipc.signal_fds[1]);
230
231 /* close any open channels */
232 for (i = 0; i < UIPC_CH_NUM; i++) {
233 uipc_close_ch_locked(uipc, i);
234 }
235 }
236
237 /* check pending events in read task */
uipc_check_task_flags_locked(tUIPC_STATE & uipc)238 static void uipc_check_task_flags_locked(tUIPC_STATE& uipc) {
239 int i;
240
241 for (i = 0; i < UIPC_CH_NUM; i++) {
242 if (uipc.ch[i].task_evt_flags & UIPC_TASK_FLAG_DISCONNECT_CHAN) {
243 uipc.ch[i].task_evt_flags &= ~UIPC_TASK_FLAG_DISCONNECT_CHAN;
244 uipc_close_ch_locked(uipc, i);
245 }
246
247 /* add here */
248 }
249 }
250
uipc_check_fd_locked(tUIPC_STATE & uipc,tUIPC_CH_ID ch_id)251 static int uipc_check_fd_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
252 if (ch_id >= UIPC_CH_NUM) {
253 return -1;
254 }
255
256 if (SAFE_FD_ISSET(uipc.ch[ch_id].srvfd, &uipc.read_set)) {
257 log::debug("INCOMING CONNECTION ON CH {}", ch_id);
258
259 // Close the previous connection
260 if (uipc.ch[ch_id].fd != UIPC_DISCONNECTED) {
261 log::debug("CLOSE CONNECTION (FD {})", uipc.ch[ch_id].fd);
262 close(uipc.ch[ch_id].fd);
263 FD_CLR(uipc.ch[ch_id].fd, &uipc.active_set);
264 uipc.ch[ch_id].fd = UIPC_DISCONNECTED;
265 }
266
267 uipc.ch[ch_id].fd = accept_server_socket(uipc.ch[ch_id].srvfd);
268
269 log::debug("NEW FD {}", uipc.ch[ch_id].fd);
270
271 if ((uipc.ch[ch_id].fd >= 0) && uipc.ch[ch_id].cback) {
272 /* if we have a callback we should add this fd to the active set
273 and notify user with callback event */
274 log::debug("ADD FD {} TO ACTIVE SET", uipc.ch[ch_id].fd);
275 FD_SET(uipc.ch[ch_id].fd, &uipc.active_set);
276 uipc.max_fd = MAX(uipc.max_fd, uipc.ch[ch_id].fd);
277 }
278
279 if (uipc.ch[ch_id].fd < 0) {
280 log::error("FAILED TO ACCEPT CH {}", ch_id);
281 return -1;
282 }
283
284 if (uipc.ch[ch_id].cback) {
285 uipc.ch[ch_id].cback(ch_id, UIPC_OPEN_EVT);
286 }
287 }
288
289 if (SAFE_FD_ISSET(uipc.ch[ch_id].fd, &uipc.read_set)) {
290 if (uipc.ch[ch_id].cback) {
291 uipc.ch[ch_id].cback(ch_id, UIPC_RX_DATA_READY_EVT);
292 }
293 }
294 return 0;
295 }
296
uipc_check_interrupt_locked(tUIPC_STATE & uipc)297 static void uipc_check_interrupt_locked(tUIPC_STATE& uipc) {
298 if (SAFE_FD_ISSET(uipc.signal_fds[0], &uipc.read_set)) {
299 char sig_recv = 0;
300 OSI_NO_INTR(recv(uipc.signal_fds[0], &sig_recv, sizeof(sig_recv), MSG_WAITALL));
301 }
302 }
303
uipc_wakeup_locked(tUIPC_STATE & uipc)304 static inline void uipc_wakeup_locked(tUIPC_STATE& uipc) {
305 char sig_on = 1;
306 log::debug("UIPC SEND WAKE UP");
307
308 OSI_NO_INTR(send(uipc.signal_fds[1], &sig_on, sizeof(sig_on), 0));
309 }
310
uipc_setup_server_locked(tUIPC_STATE & uipc,tUIPC_CH_ID ch_id,const char * name,tUIPC_RCV_CBACK * cback)311 static int uipc_setup_server_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id, const char* name,
312 tUIPC_RCV_CBACK* cback) {
313 int fd;
314
315 log::debug("SETUP CHANNEL SERVER {}", ch_id);
316
317 if (ch_id >= UIPC_CH_NUM) {
318 return -1;
319 }
320
321 std::lock_guard<std::recursive_mutex> guard(uipc.mutex);
322
323 fd = create_server_socket(name);
324
325 if (fd < 0) {
326 log::error("failed to setup {}: {}", name, strerror(errno));
327 return -1;
328 }
329
330 log::debug("ADD SERVER FD TO ACTIVE SET {}", fd);
331 FD_SET(fd, &uipc.active_set);
332 uipc.max_fd = MAX(uipc.max_fd, fd);
333
334 uipc.ch[ch_id].srvfd = fd;
335 uipc.ch[ch_id].cback = cback;
336 uipc.ch[ch_id].read_poll_tmo_ms = DEFAULT_READ_POLL_TMO_MS;
337
338 /* trigger main thread to update read set */
339 uipc_wakeup_locked(uipc);
340
341 return 0;
342 }
343
uipc_flush_ch_locked(tUIPC_STATE & uipc,tUIPC_CH_ID ch_id)344 static void uipc_flush_ch_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
345 char buf[UIPC_FLUSH_BUFFER_SIZE];
346 struct pollfd pfd;
347
348 pfd.events = POLLIN;
349 pfd.fd = uipc.ch[ch_id].fd;
350
351 if (uipc.ch[ch_id].fd == UIPC_DISCONNECTED) {
352 log::debug("fd disconnected. Exiting");
353 return;
354 }
355
356 while (1) {
357 int ret;
358 OSI_NO_INTR(ret = poll(&pfd, 1, 1));
359 if (ret == 0) {
360 log::verbose("poll() timeout - nothing to do. Exiting");
361 return;
362 }
363 if (ret < 0) {
364 log::warn("poll() failed: return {} errno {} ({}). Exiting", ret, errno, strerror(errno));
365 return;
366 }
367 log::verbose("polling fd {}, revents: 0x{:x}, ret {}", pfd.fd, pfd.revents, ret);
368 if (pfd.revents & (POLLERR | POLLHUP)) {
369 log::warn("POLLERR or POLLHUP. Exiting");
370 return;
371 }
372
373 /* read sufficiently large buffer to ensure flush empties socket faster than
374 it is getting refilled */
375 (void)read(pfd.fd, &buf, UIPC_FLUSH_BUFFER_SIZE);
376 }
377 }
378
uipc_flush_locked(tUIPC_STATE & uipc,tUIPC_CH_ID ch_id)379 static void uipc_flush_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
380 if (ch_id >= UIPC_CH_NUM) {
381 return;
382 }
383
384 switch (ch_id) {
385 case UIPC_CH_ID_AV_CTRL:
386 uipc_flush_ch_locked(uipc, UIPC_CH_ID_AV_CTRL);
387 break;
388
389 case UIPC_CH_ID_AV_AUDIO:
390 uipc_flush_ch_locked(uipc, UIPC_CH_ID_AV_AUDIO);
391 break;
392 }
393 }
394
uipc_close_ch_locked(tUIPC_STATE & uipc,tUIPC_CH_ID ch_id)395 static int uipc_close_ch_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
396 int wakeup = 0;
397
398 log::debug("CLOSE CHANNEL {}", ch_id);
399
400 if (ch_id >= UIPC_CH_NUM) {
401 return -1;
402 }
403
404 if (uipc.ch[ch_id].srvfd != UIPC_DISCONNECTED) {
405 log::debug("CLOSE SERVER (FD {})", uipc.ch[ch_id].srvfd);
406 close(uipc.ch[ch_id].srvfd);
407 FD_CLR(uipc.ch[ch_id].srvfd, &uipc.active_set);
408 uipc.ch[ch_id].srvfd = UIPC_DISCONNECTED;
409 wakeup = 1;
410 }
411
412 if (uipc.ch[ch_id].fd != UIPC_DISCONNECTED) {
413 log::debug("CLOSE CONNECTION (FD {})", uipc.ch[ch_id].fd);
414 close(uipc.ch[ch_id].fd);
415 FD_CLR(uipc.ch[ch_id].fd, &uipc.active_set);
416 uipc.ch[ch_id].fd = UIPC_DISCONNECTED;
417 wakeup = 1;
418 }
419
420 /* notify this connection is closed */
421 if (uipc.ch[ch_id].cback) {
422 uipc.ch[ch_id].cback(ch_id, UIPC_CLOSE_EVT);
423 }
424
425 /* trigger main thread update if something was updated */
426 if (wakeup) {
427 uipc_wakeup_locked(uipc);
428 }
429
430 return 0;
431 }
432
uipc_close_locked(tUIPC_STATE & uipc,tUIPC_CH_ID ch_id)433 static void uipc_close_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
434 if (uipc.ch[ch_id].srvfd == UIPC_DISCONNECTED) {
435 log::debug("CHANNEL {} ALREADY CLOSED", ch_id);
436 return;
437 }
438
439 /* schedule close on this channel */
440 uipc.ch[ch_id].task_evt_flags |= UIPC_TASK_FLAG_DISCONNECT_CHAN;
441 uipc_wakeup_locked(uipc);
442 }
443
uipc_read_task(void * arg)444 static void* uipc_read_task(void* arg) {
445 tUIPC_STATE& uipc = *((tUIPC_STATE*)arg);
446 int ch_id;
447 int result;
448
449 prctl(PR_SET_NAME, (unsigned long)"uipc-main", 0, 0, 0);
450
451 while (uipc.running) {
452 uipc.read_set = uipc.active_set;
453
454 result = select(uipc.max_fd + 1, &uipc.read_set, NULL, NULL, NULL);
455
456 if (result == 0) {
457 log::debug("select timeout");
458 continue;
459 }
460 if (result < 0) {
461 if (errno != EINTR) {
462 log::debug("select failed {}", strerror(errno));
463 }
464 continue;
465 }
466
467 {
468 std::lock_guard<std::recursive_mutex> guard(uipc.mutex);
469
470 /* clear any wakeup interrupt */
471 uipc_check_interrupt_locked(uipc);
472
473 /* check pending task events */
474 uipc_check_task_flags_locked(uipc);
475
476 /* make sure we service audio channel first */
477 uipc_check_fd_locked(uipc, UIPC_CH_ID_AV_AUDIO);
478
479 /* check for other connections */
480 for (ch_id = 0; ch_id < UIPC_CH_NUM; ch_id++) {
481 if (ch_id != UIPC_CH_ID_AV_AUDIO) {
482 uipc_check_fd_locked(uipc, ch_id);
483 }
484 }
485 }
486 }
487
488 log::debug("UIPC READ THREAD EXITING");
489
490 uipc_main_cleanup(uipc);
491
492 uipc.tid = 0;
493
494 log::debug("UIPC READ THREAD DONE");
495
496 return nullptr;
497 }
498
uipc_start_main_server_thread(tUIPC_STATE & uipc)499 static int uipc_start_main_server_thread(tUIPC_STATE& uipc) {
500 uipc.running = 1;
501
502 if (pthread_create(&uipc.tid, (const pthread_attr_t*)NULL, uipc_read_task, &uipc) != 0) {
503 log::error("uipc_thread_create pthread_create failed:{}", errno);
504 return -1;
505 }
506
507 return 0;
508 }
509
510 /* blocking call */
uipc_stop_main_server_thread(tUIPC_STATE & uipc)511 static void uipc_stop_main_server_thread(tUIPC_STATE& uipc) {
512 /* request shutdown of read thread */
513 {
514 std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
515 uipc.running = 0;
516 uipc_wakeup_locked(uipc);
517 }
518
519 /* wait until read thread is fully terminated */
520 /* tid might hold pointer value where it's value
521 is negative value with signed bit is set, so
522 corrected the logic to check zero or non zero */
523 if (uipc.tid) {
524 pthread_join(uipc.tid, NULL);
525 }
526 }
527
528 /*******************************************************************************
529 **
530 ** Function UIPC_Init
531 **
532 ** Description Initialize UIPC module
533 **
534 ** Returns void
535 **
536 ******************************************************************************/
UIPC_Init()537 std::unique_ptr<tUIPC_STATE> UIPC_Init() {
538 std::unique_ptr<tUIPC_STATE> uipc = std::make_unique<tUIPC_STATE>();
539 log::debug("UIPC_Init");
540
541 std::lock_guard<std::recursive_mutex> lock(uipc->mutex);
542
543 uipc_main_init(*uipc);
544 uipc_start_main_server_thread(*uipc);
545
546 return uipc;
547 }
548
549 /*******************************************************************************
550 **
551 ** Function UIPC_Open
552 **
553 ** Description Open UIPC interface
554 **
555 ** Returns true in case of success, false in case of failure.
556 **
557 ******************************************************************************/
UIPC_Open(tUIPC_STATE & uipc,tUIPC_CH_ID ch_id,tUIPC_RCV_CBACK * p_cback,const char * socket_path)558 bool UIPC_Open(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id, tUIPC_RCV_CBACK* p_cback,
559 const char* socket_path) {
560 log::debug("UIPC_Open : ch_id {}", ch_id);
561
562 std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
563
564 if (ch_id >= UIPC_CH_NUM) {
565 return false;
566 }
567
568 if (uipc.ch[ch_id].srvfd != UIPC_DISCONNECTED) {
569 log::debug("CHANNEL {} ALREADY OPEN", ch_id);
570 return 0;
571 }
572
573 uipc_setup_server_locked(uipc, ch_id, socket_path, p_cback);
574
575 return true;
576 }
577
578 /*******************************************************************************
579 **
580 ** Function UIPC_Close
581 **
582 ** Description Close UIPC interface
583 **
584 ** Returns void
585 **
586 ******************************************************************************/
UIPC_Close(tUIPC_STATE & uipc,tUIPC_CH_ID ch_id)587 void UIPC_Close(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
588 log::debug("UIPC_Close : ch_id {}", ch_id);
589
590 /* special case handling uipc shutdown */
591 if (ch_id != UIPC_CH_ID_ALL) {
592 std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
593 uipc_close_locked(uipc, ch_id);
594 return;
595 }
596
597 log::debug("UIPC_Close : waiting for shutdown to complete");
598 uipc_stop_main_server_thread(uipc);
599 log::debug("UIPC_Close : shutdown complete");
600 }
601
602 /*******************************************************************************
603 **
604 ** Function UIPC_Send
605 **
606 ** Description Called to transmit a message over UIPC.
607 **
608 ** Returns true in case of success, false in case of failure.
609 **
610 ******************************************************************************/
UIPC_Send(tUIPC_STATE & uipc,tUIPC_CH_ID ch_id,uint16_t,const uint8_t * p_buf,uint16_t msglen)611 bool UIPC_Send(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id, uint16_t /* msg_evt */, const uint8_t* p_buf,
612 uint16_t msglen) {
613 log::verbose("UIPC_Send : ch_id:{} {} bytes", ch_id, msglen);
614
615 std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
616
617 ssize_t ret;
618 OSI_NO_INTR(ret = write(uipc.ch[ch_id].fd, p_buf, msglen));
619 if (ret < 0) {
620 log::error("failed to write ({})", strerror(errno));
621 return false;
622 }
623
624 return true;
625 }
626
627 /*******************************************************************************
628 **
629 ** Function UIPC_Read
630 **
631 ** Description Called to read a message from UIPC.
632 **
633 ** Returns return the number of bytes read.
634 **
635 ******************************************************************************/
636
UIPC_Read(tUIPC_STATE & uipc,tUIPC_CH_ID ch_id,uint8_t * p_buf,uint32_t len)637 uint32_t UIPC_Read(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id, uint8_t* p_buf, uint32_t len) {
638 if (ch_id >= UIPC_CH_NUM) {
639 log::error("UIPC_Read : invalid ch id {}", ch_id);
640 return 0;
641 }
642
643 int n_read = 0;
644 int fd = uipc.ch[ch_id].fd;
645 struct pollfd pfd;
646
647 if (fd == UIPC_DISCONNECTED) {
648 log::error("UIPC_Read : channel {} closed", ch_id);
649 return 0;
650 }
651
652 while (n_read < (int)len) {
653 pfd.fd = fd;
654 pfd.events = POLLIN | POLLHUP;
655
656 /* make sure there is data prior to attempting read to avoid blocking
657 a read for more than poll timeout */
658
659 int poll_ret;
660 OSI_NO_INTR(poll_ret = poll(&pfd, 1, uipc.ch[ch_id].read_poll_tmo_ms));
661 if (poll_ret == 0) {
662 log::warn("poll timeout ({} ms)", uipc.ch[ch_id].read_poll_tmo_ms);
663 break;
664 }
665 if (poll_ret < 0) {
666 log::error("poll() failed: return {} errno {} ({})", poll_ret, errno, strerror(errno));
667 break;
668 }
669
670 if (pfd.revents & (POLLHUP | POLLNVAL)) {
671 log::warn("poll : channel detached remotely");
672 std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
673 uipc_close_locked(uipc, ch_id);
674 return 0;
675 }
676
677 ssize_t n;
678 OSI_NO_INTR(n = recv(fd, p_buf + n_read, len - n_read, 0));
679
680 if (n == 0) {
681 log::warn("UIPC_Read : channel detached remotely");
682 std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
683 uipc_close_locked(uipc, ch_id);
684 return 0;
685 }
686
687 if (n < 0) {
688 log::warn("UIPC_Read : read failed ({})", strerror(errno));
689 return 0;
690 }
691
692 n_read += n;
693 }
694
695 return n_read;
696 }
697
698 /*******************************************************************************
699 *
700 * Function UIPC_Ioctl
701 *
702 * Description Called to control UIPC.
703 *
704 * Returns void
705 *
706 ******************************************************************************/
707
UIPC_Ioctl(tUIPC_STATE & uipc,tUIPC_CH_ID ch_id,uint32_t request,void * param)708 bool UIPC_Ioctl(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id, uint32_t request, void* param) {
709 log::debug("#### UIPC_Ioctl : ch_id {}, request {} ####", ch_id, request);
710 std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
711
712 switch (request) {
713 case UIPC_REQ_RX_FLUSH:
714 uipc_flush_locked(uipc, ch_id);
715 break;
716
717 case UIPC_REG_REMOVE_ACTIVE_READSET:
718 /* user will read data directly and not use select loop */
719 if (uipc.ch[ch_id].fd != UIPC_DISCONNECTED) {
720 /* remove this channel from active set */
721 FD_CLR(uipc.ch[ch_id].fd, &uipc.active_set);
722
723 /* refresh active set */
724 uipc_wakeup_locked(uipc);
725 }
726 break;
727
728 case UIPC_SET_READ_POLL_TMO:
729 uipc.ch[ch_id].read_poll_tmo_ms = (intptr_t)param;
730 log::debug("UIPC_SET_READ_POLL_TMO : CH {}, TMO {} ms", ch_id,
731 uipc.ch[ch_id].read_poll_tmo_ms);
732 break;
733
734 default:
735 log::debug("UIPC_Ioctl : request not handled ({})", request);
736 break;
737 }
738
739 return false;
740 }
741