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 
17 typedef struct pty_server pty_server_t;
18 typedef struct pty_client pty_client_t;
19 
20 struct 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
62 void 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
67 zx_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.
72 void pty_server_resume_locked(pty_server_t* ps);
73 
74 void 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
78 zx_status_t pty_server_openat(void* ctx, zx_device_t** out, const char* path, uint32_t flags);
79 void pty_server_release(void* ctx);
80 
81 __END_CDECLS;
82