1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12#pragma once
13
14#include <sys/types.h>
15#include <stdint.h>
16
17#include <sel4/sel4.h>
18
19#include <simple/simple.h>
20#include <sel4utils/thread.h>
21#include <vka/vka.h>
22#include <vka/object.h>
23#include <vspace/vspace.h>
24
25/** @file API for making requests to a serial server multiplexing thread.
26 *
27 * If CONFIG_SERIAL_SERVER_COLOURED_OUTPUT is set, the output will also
28 * be wrapped in ansi escape codes which allow client code to be identified
29 * in a terminal.
30 *
31 * By default, the new thread which is created by this API will share the
32 * CSpace and VSpace of its creator. Each client of the server thread is required
33 * to have a badged cap to the Endpoint that the Server is listening on. The
34 * badge on this Endpoint cap must have been allocated by the library's
35 * serial_server_badge_value_alloc() or serial_server_badge_value_get_unused()
36 * function.
37 *
38 * Establishing a connection to the server is as simple as calling:
39 *  serial_client_context_t conn;
40 *  error = serial_server_client_connect(..., &conn).
41 * Then check the error value returned:
42 *  if (error != SERIAL_SERVER_NOERROR) { ... }
43 *
44 * If the connect() call was successful, make sure you save the
45 * serial_client_context_t object. Then use the serial server's printf from
46 * that point on, by passing the serial_client_context_t object:
47 *  serial_server_printf(&conn, "Hello world from %s!", "john");
48 *
49 * You can easily abstract away the long function name using preprocessor
50 * defines or wrapper functions such as:
51 *  #define printf(fmt, ...) serial_server_printf(&global_client_conn, ## __VA_ARGS__)
52 *
53 * CAUTION:
54 * All vka_t, vpsace_t, and simple_t instances passed to this library by
55 * reference must remain functional throughout the lifetime of the server.
56 */
57
58/* Context given to each client to preserve state.
59 *
60 * This is an opaque handle data type, and clients are not to assume the
61 * layout or purpose of its members.
62 */
63typedef struct _serial_client_context {
64    seL4_Word badge_value;
65    cspacepath_t badged_server_ep_cspath;
66    volatile char *shmem;
67    size_t shmem_size;
68} serial_client_context_t;
69
70/** Establishes a connection to the server thread and returns a connection
71 * handle. It is expected that this will be called by the client thread itself.
72 *
73 * CAUTION:
74 * All vka_t, vpsace_t, and simple_t instances passed to this library by
75 * reference must remain functional throughout the lifetime of the server.
76 *
77 * Can be called by any thread which has an endpoint to the thread/process
78 * that spawned the server thread.
79 * @param server_ep_cap CPtr to an endpoint between the client and the SERVER
80 *                      thread.
81 * @param client_vka Initialized vka_t for the client thread.
82 * @param client_vspace Initialized vspace_t for the client thread.
83 * @param client_badge_value Unique badge value for the connection between this
84 *                           client and the server thread. Each client of the
85 *                           server must have a unique badge value. Two clients
86 *                           connecting with the same badge value will cause the
87 *                           server to overwrite the former with the latter.
88 * @param conn [out] Connection token returned by the library. Use this to make calls
89 *             to the server thread.
90 * @return Error value: 0 on success, non-zero on failure.
91 */
92int serial_server_client_connect(seL4_CPtr server_ep_cap,
93                                 vka_t *client_vka,
94                                 vspace_t *client_vspace,
95                                 serial_client_context_t *conn);
96
97/** Sends a request to the server to print a message to the serial.
98 *
99 * @param ctxt Valid connection token returned by serial_server_client_connect().
100 * @param fmt Valid printf format specifier string.
101 * @param ... Variadic argument list for printf.
102 * @return The number of characters printed. If the call had to be aborted due
103 *         to an error condition, a negative error code is returned.
104 */
105ssize_t serial_server_printf(serial_client_context_t *ctxt, const char *fmt, ...);
106
107
108/** Sends the server a request to print the current contents of the shared memory buffer.
109 *  For use when the client uses the shared memory buffer directly.
110 *
111 * @param ctxt Valid connection token returned by serial_server_client_connect().
112 * @param len the size of the buffer data.
113 * @return The number of bytes written (positive integer), or a negative integer
114 *         for error condition.
115 *
116 */
117ssize_t serial_server_flush(serial_client_context_t *ctxt, ssize_t len);
118
119/** Sends a request to the server to write a fixed-length buffer to the serial.
120 *
121 * @param ctxt Valid connection token returned by serial_server_client_connect().
122 * @param in_buff Input buffer of data.
123 * @param len the size of the buffer data.
124 * @return The number of bytes written (positive integer), or a negative integer
125 *         for error condition.
126 */
127ssize_t serial_server_write(serial_client_context_t *ctxt, const char *in_buff, ssize_t len);
128
129/** Sends a request to the server to disconnect the calling client.
130 *
131 * Causes the server to release the connection metadata it holds about the
132 * client in question and teardown the shared memory mapping between the server
133 * and that client.
134 * @param ctxt Initialized connection token returned from
135 *             serial_server_client_connect().
136 */
137void serial_server_disconnect(serial_client_context_t *ctxt);
138
139/** Sends a request to the server to "kill" itself.
140 *
141 * In practice, right now that means that the server exits its message loop and
142 * stops listening for IPC from clients, and then seL4_TCB_Suspend()s itself.
143 * @param conn Connection handle to the server, returned by
144 *             serial_server_client_connect().
145 * @return Integer value: 0 on successfull "kill", non-zero if the server was
146 *         unable to shutdown for some reason.
147 */
148int serial_server_kill(serial_client_context_t *conn);
149