1/*
2 * Copyright 2004-2006, Axel D��rfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef TTY_PRIVATE_H
6#define TTY_PRIVATE_H
7
8#include <termios.h>
9
10#include <Drivers.h>
11#include <KernelExport.h>
12#include <tty/tty_module.h>
13
14#include <condition_variable.h>
15#include <fs/select_sync_pool.h>
16#include <lock.h>
17#include <util/DoublyLinkedList.h>
18
19#include "line_buffer.h"
20
21
22#define TTY_BUFFER_SIZE 4096
23
24// The only nice Rico'ism :)
25#define CTRL(c)	((c) - 0100)
26
27
28class RequestOwner;
29class Semaphore;
30struct tty;
31struct tty_cookie;
32
33class Request : public DoublyLinkedListLinkImpl<Request> {
34	public:
35		Request();
36
37		void Init(RequestOwner *owner, tty_cookie *cookie, size_t bytesNeeded);
38
39		tty_cookie *TTYCookie() const	{ return fCookie; }
40
41		void Notify(size_t bytesAvailable);
42		void NotifyError(status_t error);
43
44		bool WasNotified() const		{ return fNotified; }
45		bool HasError() const			{ return fError; }
46
47		void Dump(const char* prefix);
48
49	private:
50		RequestOwner	*fOwner;
51		tty_cookie		*fCookie;
52		size_t			fBytesNeeded;
53		bool			fNotified;
54		bool			fError;
55};
56
57class RequestQueue {
58	public:
59		RequestQueue();
60		~RequestQueue()	{}
61
62		void Add(Request *request);
63		void Remove(Request *request);
64
65		Request *First() const				{ return fRequests.First(); }
66		bool IsEmpty() const				{ return fRequests.IsEmpty(); }
67
68		void NotifyFirst(size_t bytesAvailable);
69		void NotifyError(status_t error);
70		void NotifyError(tty_cookie *cookie, status_t error);
71
72		void Dump(const char* prefix);
73
74	private:
75		typedef DoublyLinkedList<Request> RequestList;
76
77		RequestList	fRequests;
78};
79
80class RequestOwner {
81	public:
82		RequestOwner();
83
84		void Enqueue(tty_cookie *cookie, RequestQueue *queue1,
85			RequestQueue *queue2 = NULL);
86		void Dequeue();
87
88		void SetBytesNeeded(size_t bytesNeeded);
89		size_t BytesNeeded() const	{ return fBytesNeeded; }
90
91		status_t Wait(bool interruptable, bigtime_t timeout = B_INFINITE_TIMEOUT);
92
93		bool IsFirstInQueues();
94
95		void Notify(Request *request);
96		void NotifyError(Request *request, status_t error);
97
98		status_t Error() const	{ return fError; }
99
100	private:
101		ConditionVariable*		fConditionVariable;
102		tty_cookie*				fCookie;
103		status_t				fError;
104		RequestQueue*			fRequestQueues[2];
105		Request					fRequests[2];
106		size_t					fBytesNeeded;
107};
108
109
110struct tty_cookie : DoublyLinkedListLinkImpl<tty_cookie> {
111	struct tty			*tty;
112	struct tty			*other_tty;
113	uint32				open_mode;
114	int32				thread_count;
115	sem_id				blocking_semaphore;
116	bool				closed;
117};
118
119typedef DoublyLinkedList<tty_cookie> TTYCookieList;
120
121struct tty_settings {
122	pid_t				pgrp_id;
123	pid_t				session_id;
124	struct termios		termios;
125	struct winsize		window_size;
126};
127
128struct tty {
129	int32				ref_count;	// referenced by cookies
130	int32				open_count;
131	int32				opened_count;
132	select_sync_pool*	select_pool;
133	RequestQueue		reader_queue;
134	RequestQueue		writer_queue;
135	TTYCookieList		cookies;
136	line_buffer			input_buffer;
137	tty_service_func	service_func;
138	uint32				pending_eof;
139	bool				is_master;
140	recursive_lock*		lock;
141	tty_settings*		settings;
142	uint8				hardware_bits;
143	bool				is_exclusive;
144};
145
146
147extern struct mutex gTTYCookieLock;
148extern struct recursive_lock gTTYRequestLock;
149
150extern status_t tty_create(tty_service_func func, struct tty *masterTTY,
151	struct tty **tty);
152extern void tty_destroy(struct tty *tty);
153
154extern status_t tty_create_cookie(struct tty *tty, struct tty *otherTTY,
155	uint32 openMode, struct tty_cookie **cookie);
156extern void tty_destroy_cookie(tty_cookie *cookie);
157extern void tty_close_cookie(tty_cookie *cookie);
158
159extern status_t tty_read(tty_cookie *cookie, void *buffer, size_t *_length);
160extern status_t tty_write(tty_cookie *sourceCookie, const void *buffer,
161	size_t *_length);
162extern status_t tty_control(tty_cookie *cookie, uint32 op, void *buffer,
163	size_t length);
164extern status_t tty_select(tty_cookie *cookie, uint8 event, uint32 ref,
165	selectsync *sync);
166extern status_t tty_deselect(tty_cookie *cookie, uint8 event, selectsync *sync);
167
168extern status_t tty_input_lock(tty_cookie* cookie, bool lock);
169extern status_t tty_hardware_signal(tty_cookie* cookie, int signal, bool);
170
171#endif	/* TTY_PRIVATE_H */
172