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#pragma once
6
7#include <stdint.h>
8#include <threads.h>
9
10#include <ddk/device.h>
11
12#include <zircon/compiler.h>
13#include <zircon/listnode.h>
14
15__BEGIN_CDECLS;
16
17typedef struct pty_server pty_server_t;
18typedef struct pty_client pty_client_t;
19
20struct pty_server {
21    zx_device_t* zxdev;
22
23    // lock covers server and all its clients
24    mtx_t lock;
25
26    // track server lifetime
27    int32_t refcount;
28
29    // pending OOB events
30    uint32_t events;
31
32    // list of all clients
33    list_node_t clients;
34
35    // active client receives inbound data
36    pty_client_t* active;
37
38    // control client receives events
39    pty_client_t* control;
40
41    // called when data is written by active client
42    // pty_server's lock is held across this call
43    // (it is not legal to call back into any pty_server_*() functions)
44    zx_status_t (*recv)(pty_server_t* ps, const void* data, size_t len, size_t* actual);
45
46    // if non-null, called for unhandled client ioctl ops
47    // no lock is held across this call
48    zx_status_t (*ioctl)(pty_server_t* ps, uint32_t op,
49                     const void* cmd, size_t cmdlen,
50                     void* out, size_t outlen, size_t* out_actual);
51
52    // called when pty_server_t should be deleted
53    // if NULL, free(ps) is called instead
54    void (*release)(pty_server_t* ps);
55
56    // window size in character cells
57    uint32_t width;
58    uint32_t height;
59};
60
61// this initializes everything *except* the embedded zx_device_t
62void pty_server_init(pty_server_t* ps);
63
64// write data through to active client
65// if atomic is true, the send will be all-or-nothing
66// if atomic is true ^c, etc processing is not done
67zx_status_t pty_server_send(pty_server_t* ps, const void* data, size_t len, bool atomic, size_t* actual);
68
69// If the recv callback returns ZX_ERR_SHOULD_WAIT, pty_server_resume()
70// must be called when it is possible to call it successfully again.
71// ps->lock must be held.
72void pty_server_resume_locked(pty_server_t* ps);
73
74void pty_server_set_window_size(pty_server_t* ps, uint32_t w, uint32_t h);
75
76// device ops for pty_server
77// the zx_device_t here must be the one embedded in pty_server_t
78zx_status_t pty_server_openat(void* ctx, zx_device_t** out, const char* path, uint32_t flags);
79void pty_server_release(void* ctx);
80
81__END_CDECLS;
82