|  | /* | 
|  | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) | 
|  | * | 
|  | * SPDX-License-Identifier: BSD-2-Clause | 
|  | */ | 
|  | #pragma once | 
|  |  | 
|  | #include <sys/types.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <sel4/sel4.h> | 
|  |  | 
|  | #include <simple/simple.h> | 
|  | #include <sel4utils/thread.h> | 
|  | #include <vka/vka.h> | 
|  | #include <vka/object.h> | 
|  | #include <vspace/vspace.h> | 
|  |  | 
|  | /** @file API for making requests to a serial server multiplexing thread. | 
|  | * | 
|  | * If CONFIG_SERIAL_SERVER_COLOURED_OUTPUT is set, the output will also | 
|  | * be wrapped in ansi escape codes which allow client code to be identified | 
|  | * in a terminal. | 
|  | * | 
|  | * By default, the new thread which is created by this API will share the | 
|  | * CSpace and VSpace of its creator. Each client of the server thread is required | 
|  | * to have a badged cap to the Endpoint that the Server is listening on. The | 
|  | * badge on this Endpoint cap must have been allocated by the library's | 
|  | * serial_server_badge_value_alloc() or serial_server_badge_value_get_unused() | 
|  | * function. | 
|  | * | 
|  | * Establishing a connection to the server is as simple as calling: | 
|  | *  serial_client_context_t conn; | 
|  | *  error = serial_server_client_connect(..., &conn). | 
|  | * Then check the error value returned: | 
|  | *  if (error != SERIAL_SERVER_NOERROR) { ... } | 
|  | * | 
|  | * If the connect() call was successful, make sure you save the | 
|  | * serial_client_context_t object. Then use the serial server's printf from | 
|  | * that point on, by passing the serial_client_context_t object: | 
|  | *  serial_server_printf(&conn, "Hello world from %s!", "john"); | 
|  | * | 
|  | * You can easily abstract away the long function name using preprocessor | 
|  | * defines or wrapper functions such as: | 
|  | *  #define printf(fmt, ...) serial_server_printf(&global_client_conn, ## __VA_ARGS__) | 
|  | * | 
|  | * CAUTION: | 
|  | * All vka_t, vpsace_t, and simple_t instances passed to this library by | 
|  | * reference must remain functional throughout the lifetime of the server. | 
|  | */ | 
|  |  | 
|  | /* Context given to each client to preserve state. | 
|  | * | 
|  | * This is an opaque handle data type, and clients are not to assume the | 
|  | * layout or purpose of its members. | 
|  | */ | 
|  | typedef struct _serial_client_context { | 
|  | seL4_Word badge_value; | 
|  | cspacepath_t badged_server_ep_cspath; | 
|  | volatile char *shmem; | 
|  | size_t shmem_size; | 
|  | } serial_client_context_t; | 
|  |  | 
|  | /** Establishes a connection to the server thread and returns a connection | 
|  | * handle. It is expected that this will be called by the client thread itself. | 
|  | * | 
|  | * CAUTION: | 
|  | * All vka_t, vpsace_t, and simple_t instances passed to this library by | 
|  | * reference must remain functional throughout the lifetime of the server. | 
|  | * | 
|  | * Can be called by any thread which has an endpoint to the thread/process | 
|  | * that spawned the server thread. | 
|  | * @param server_ep_cap CPtr to an endpoint between the client and the SERVER | 
|  | *                      thread. | 
|  | * @param client_vka Initialized vka_t for the client thread. | 
|  | * @param client_vspace Initialized vspace_t for the client thread. | 
|  | * @param client_badge_value Unique badge value for the connection between this | 
|  | *                           client and the server thread. Each client of the | 
|  | *                           server must have a unique badge value. Two clients | 
|  | *                           connecting with the same badge value will cause the | 
|  | *                           server to overwrite the former with the latter. | 
|  | * @param conn [out] Connection token returned by the library. Use this to make calls | 
|  | *             to the server thread. | 
|  | * @return Error value: 0 on success, non-zero on failure. | 
|  | */ | 
|  | int serial_server_client_connect(seL4_CPtr server_ep_cap, | 
|  | vka_t *client_vka, | 
|  | vspace_t *client_vspace, | 
|  | serial_client_context_t *conn); | 
|  |  | 
|  | /** Sends a request to the server to print a message to the serial. | 
|  | * | 
|  | * @param ctxt Valid connection token returned by serial_server_client_connect(). | 
|  | * @param fmt Valid printf format specifier string. | 
|  | * @param ... Variadic argument list for printf. | 
|  | * @return The number of characters printed. If the call had to be aborted due | 
|  | *         to an error condition, a negative error code is returned. | 
|  | */ | 
|  | ssize_t serial_server_printf(serial_client_context_t *ctxt, const char *fmt, ...); | 
|  |  | 
|  |  | 
|  | /** Sends the server a request to print the current contents of the shared memory buffer. | 
|  | *  For use when the client uses the shared memory buffer directly. | 
|  | * | 
|  | * @param ctxt Valid connection token returned by serial_server_client_connect(). | 
|  | * @param len the size of the buffer data. | 
|  | * @return The number of bytes written (positive integer), or a negative integer | 
|  | *         for error condition. | 
|  | * | 
|  | */ | 
|  | ssize_t serial_server_flush(serial_client_context_t *ctxt, ssize_t len); | 
|  |  | 
|  | /** Sends a request to the server to write a fixed-length buffer to the serial. | 
|  | * | 
|  | * @param ctxt Valid connection token returned by serial_server_client_connect(). | 
|  | * @param in_buff Input buffer of data. | 
|  | * @param len the size of the buffer data. | 
|  | * @return The number of bytes written (positive integer), or a negative integer | 
|  | *         for error condition. | 
|  | */ | 
|  | ssize_t serial_server_write(serial_client_context_t *ctxt, const char *in_buff, ssize_t len); | 
|  |  | 
|  | /** Sends a request to the server to disconnect the calling client. | 
|  | * | 
|  | * Causes the server to release the connection metadata it holds about the | 
|  | * client in question and teardown the shared memory mapping between the server | 
|  | * and that client. | 
|  | * @param ctxt Initialized connection token returned from | 
|  | *             serial_server_client_connect(). | 
|  | */ | 
|  | void serial_server_disconnect(serial_client_context_t *ctxt); | 
|  |  | 
|  | /** Sends a request to the server to "kill" itself. | 
|  | * | 
|  | * In practice, right now that means that the server exits its message loop and | 
|  | * stops listening for IPC from clients, and then seL4_TCB_Suspend()s itself. | 
|  | * @param conn Connection handle to the server, returned by | 
|  | *             serial_server_client_connect(). | 
|  | * @return Integer value: 0 on successfull "kill", non-zero if the server was | 
|  | *         unable to shutdown for some reason. | 
|  | */ | 
|  | int serial_server_kill(serial_client_context_t *conn); |