1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <stdio.h> 6#include <stdlib.h> 7#include <string.h> 8#include <unistd.h> 9 10#include <zircon/syscalls.h> 11#include <zircon/syscalls/port.h> 12 13#include <lib/fdio/private.h> 14 15#include <port/port.h> 16 17#if TRACE_PORT_API 18#define zprintf(fmt...) printf(fmt) 19#else 20#define zprintf(fmt...) do {} while (0) 21#endif 22 23zx_status_t port_init(port_t* port) { 24 zx_status_t r = zx_port_create(0, &port->handle); 25 zprintf("port_init(%p) port=%x\n", port, port->handle); 26 return r; 27} 28 29zx_status_t port_wait(port_t* port, port_handler_t* ph) { 30 zprintf("port_wait(%p, %p) obj=%x port=%x\n", 31 port, ph, ph->handle, port->handle); 32 return zx_object_wait_async(ph->handle, port->handle, 33 (uint64_t)(uintptr_t)ph, 34 ph->waitfor, ZX_WAIT_ASYNC_ONCE); 35} 36 37zx_status_t port_wait_repeating(port_t* port, port_handler_t* ph) { 38 zprintf("port_wait_repeating(%p, %p) obj=%x port=%x\n", 39 port, ph, ph->handle, port->handle); 40 return zx_object_wait_async(ph->handle, port->handle, 41 (uint64_t)(uintptr_t)ph, 42 ph->waitfor, ZX_WAIT_ASYNC_REPEATING); 43} 44 45 46zx_status_t port_cancel(port_t* port, port_handler_t* ph) { 47 zx_status_t r = zx_port_cancel(port->handle, ph->handle, 48 (uint64_t)(uintptr_t)ph); 49 zprintf("port_cancel(%p, %p) obj=%x port=%x: r = %d\n", 50 port, ph, ph->handle, port->handle, r); 51 return r; 52} 53 54zx_status_t port_queue(port_t* port, port_handler_t* ph, uint32_t evt) { 55 zx_port_packet_t pkt; 56 pkt.key = (uintptr_t)ph; 57 pkt.user.u32[0] = evt; 58 zx_status_t r = zx_port_queue(port->handle, &pkt); 59 zprintf("port_queue(%p, %p) obj=%x port=%x evt=%x: r=%d\n", 60 port, ph, ph->handle, port->handle, r, evt); 61 return r; 62} 63 64zx_status_t port_dispatch(port_t* port, zx_time_t deadline, bool once) { 65 for (;;) { 66 zx_port_packet_t pkt; 67 zx_status_t r; 68 if ((r = zx_port_wait(port->handle, deadline, &pkt)) != ZX_OK) { 69 if (r != ZX_ERR_TIMED_OUT) { 70 printf("port_dispatch: port wait failed %d\n", r); 71 } 72 return r; 73 } 74 port_handler_t* ph = (void*) (uintptr_t) pkt.key; 75 if (pkt.type == ZX_PKT_TYPE_USER) { 76 zprintf("port_dispatch(%p) port=%x ph=%p func=%p: evt=%x\n", 77 port, port->handle, ph, ph->func, pkt.user.u32[0]); 78 ph->func(ph, 0, pkt.user.u32[0]); 79 } else { 80 zprintf("port_dispatch(%p) port=%x ph=%p func=%p: signals=%x\n", 81 port, port->handle, ph, ph->func, pkt.signal.observed); 82 if (ph->func(ph, pkt.signal.observed, 0) == ZX_OK) { 83 port_wait(port, ph); 84 } 85 } 86 if (once) { 87 return ZX_OK; 88 } 89 } 90} 91 92static zx_status_t port_fd_handler_func(port_handler_t* ph, zx_signals_t signals, uint32_t evt) { 93 port_fd_handler_t* fh = (void*) ph; 94 95 if (evt) { 96 return fh->func(fh, 0, evt); 97 } else { 98 uint32_t pollevt; 99 __fdio_wait_end(fh->fdio_context, signals, &pollevt); 100 return fh->func(fh, pollevt, 0); 101 } 102} 103 104zx_status_t port_fd_handler_init(port_fd_handler_t* fh, int fd, unsigned pollevt) { 105 fdio_t* io = __fdio_fd_to_io(fd); 106 if (io == NULL) { 107 return ZX_ERR_INVALID_ARGS; 108 } 109 __fdio_wait_begin(io, pollevt, &fh->ph.handle, &fh->ph.waitfor); 110 fh->ph.func = port_fd_handler_func; 111 fh->fdio_context = io; 112 return ZX_OK; 113} 114 115void port_fd_handler_done(port_fd_handler_t* fh) { 116 __fdio_release(fh->fdio_context); 117 fh->fdio_context = NULL; 118 fh->ph.handle = ZX_HANDLE_INVALID; 119 fh->ph.waitfor = 0; 120} 121