1// Copyright 2017 The Fuchsia Authors
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT
6
7#include <err.h>
8#include <inttypes.h>
9#include <platform.h>
10#include <stdint.h>
11#include <stdlib.h>
12#include <trace.h>
13
14#include <lib/user_copy/user_ptr.h>
15#include <object/fifo_dispatcher.h>
16#include <object/handle.h>
17#include <object/process_dispatcher.h>
18
19#include <zircon/syscalls/policy.h>
20#include <fbl/ref_ptr.h>
21
22#include "priv.h"
23
24#define LOCAL_TRACE 0
25
26zx_status_t sys_fifo_create(size_t count, size_t elemsize, uint32_t options,
27                            user_out_handle* out0, user_out_handle* out1) {
28    auto up = ProcessDispatcher::GetCurrent();
29    zx_status_t res = up->QueryPolicy(ZX_POL_NEW_FIFO);
30    if (res != ZX_OK)
31        return res;
32
33    fbl::RefPtr<Dispatcher> dispatcher0;
34    fbl::RefPtr<Dispatcher> dispatcher1;
35    zx_rights_t rights;
36    zx_status_t result = FifoDispatcher::Create(count, elemsize, options,
37                                                &dispatcher0, &dispatcher1, &rights);
38
39    if (result == ZX_OK)
40        result = out0->make(fbl::move(dispatcher0), rights);
41    if (result == ZX_OK)
42        result = out1->make(fbl::move(dispatcher1), rights);
43    return result;
44}
45
46zx_status_t sys_fifo_write(zx_handle_t handle, size_t elem_size, user_in_ptr<const void> entries,
47                           size_t count, user_out_ptr<size_t> actual_out) {
48    auto up = ProcessDispatcher::GetCurrent();
49
50    fbl::RefPtr<FifoDispatcher> fifo;
51    zx_status_t status = up->GetDispatcherWithRights(handle, ZX_RIGHT_WRITE, &fifo);
52    if (status != ZX_OK)
53        return status;
54
55    size_t actual;
56    status = fifo->WriteFromUser(elem_size, entries.reinterpret<const uint8_t>(), count, &actual);
57    if (status != ZX_OK)
58        return status;
59
60    if (actual_out) {
61        status = actual_out.copy_to_user(actual);
62        if (status != ZX_OK)
63            return status;
64    }
65    return ZX_OK;
66}
67
68zx_status_t sys_fifo_read(zx_handle_t handle, size_t elem_size, user_out_ptr<void> entries,
69                          size_t count, user_out_ptr<size_t> actual_out) {
70    auto up = ProcessDispatcher::GetCurrent();
71
72    fbl::RefPtr<FifoDispatcher> fifo;
73    zx_status_t status = up->GetDispatcherWithRights(handle, ZX_RIGHT_READ, &fifo);
74    if (status != ZX_OK)
75        return status;
76
77    size_t actual;
78    status = fifo->ReadToUser(elem_size, entries.reinterpret<uint8_t>(), count, &actual);
79    if (status != ZX_OK)
80        return status;
81
82    if (actual_out) {
83        status = actual_out.copy_to_user(actual);
84        if (status != ZX_OK)
85            return status;
86    }
87    return ZX_OK;
88}
89