1/*
2 * Copyright 2004-2006, Axel D��rfler, axeld@pinc-software.de. All rights reserved.
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
13#include <condition_variable.h>
14#include <fs/select_sync_pool.h>
15#include <lock.h>
16#include <util/DoublyLinkedList.h>
17
18#include "line_buffer.h"
19
20
21#define TTY_BUFFER_SIZE 4096
22
23// The only nice Rico'ism :)
24#define CTRL(c)	((c) - 0100)
25
26
27typedef status_t (*tty_service_func)(struct tty *tty, uint32 op);
28	// not yet used...
29
30
31class RequestOwner;
32class Semaphore;
33struct tty;
34struct tty_cookie;
35
36class Request : public DoublyLinkedListLinkImpl<Request> {
37	public:
38		Request();
39
40		void Init(RequestOwner *owner, tty_cookie *cookie, size_t bytesNeeded);
41
42		tty_cookie *TTYCookie() const	{ return fCookie; }
43
44		void Notify(size_t bytesAvailable);
45		void NotifyError(status_t error);
46
47		bool WasNotified() const		{ return fNotified; }
48		bool HasError() const			{ return fError; }
49
50		void Dump(const char* prefix);
51
52	private:
53		RequestOwner	*fOwner;
54		tty_cookie		*fCookie;
55		size_t			fBytesNeeded;
56		bool			fNotified;
57		bool			fError;
58};
59
60class RequestQueue {
61	public:
62		RequestQueue();
63		~RequestQueue()	{}
64
65		void Add(Request *request);
66		void Remove(Request *request);
67
68		Request *First() const				{ return fRequests.First(); }
69		bool IsEmpty() const				{ return fRequests.IsEmpty(); }
70
71		void NotifyFirst(size_t bytesAvailable);
72		void NotifyError(status_t error);
73		void NotifyError(tty_cookie *cookie, status_t error);
74
75		void Dump(const char* prefix);
76
77	private:
78		typedef DoublyLinkedList<Request> RequestList;
79
80		RequestList	fRequests;
81};
82
83class RequestOwner {
84	public:
85		RequestOwner();
86
87		void Enqueue(tty_cookie *cookie, RequestQueue *queue1,
88			RequestQueue *queue2 = NULL);
89		void Dequeue();
90
91		void SetBytesNeeded(size_t bytesNeeded);
92		size_t BytesNeeded() const	{ return fBytesNeeded; }
93
94		status_t Wait(bool interruptable, bigtime_t timeout = B_INFINITE_TIMEOUT);
95
96		bool IsFirstInQueues();
97
98		void Notify(Request *request);
99		void NotifyError(Request *request, status_t error);
100
101		status_t Error() const	{ return fError; }
102
103	private:
104		ConditionVariable*		fConditionVariable;
105		tty_cookie*				fCookie;
106		status_t				fError;
107		RequestQueue*			fRequestQueues[2];
108		Request					fRequests[2];
109		size_t					fBytesNeeded;
110};
111
112
113struct tty_cookie : DoublyLinkedListLinkImpl<tty_cookie> {
114	struct tty			*tty;
115	struct tty			*other_tty;
116	uint32				open_mode;
117	int32				thread_count;
118	sem_id				blocking_semaphore;
119	bool				closed;
120};
121
122typedef DoublyLinkedList<tty_cookie> TTYCookieList;
123
124struct tty_settings {
125	pid_t				pgrp_id;
126	pid_t				session_id;
127	struct termios		termios;
128	struct winsize		window_size;
129};
130
131struct tty {
132	int32				ref_count;	// referenced by cookies
133	int32				open_count;
134	int32				index;
135	struct mutex*		lock;
136	tty_settings*		settings;
137	select_sync_pool*	select_pool;
138	RequestQueue		reader_queue;
139	RequestQueue		writer_queue;
140	TTYCookieList		cookies;
141	line_buffer			input_buffer;
142	tty_service_func	service_func;
143	uint32				pending_eof;
144	bool				is_master;
145};
146
147static const uint32 kNumTTYs = 64;
148
149extern char *gDeviceNames[kNumTTYs * 2 + 3];
150
151extern tty gMasterTTYs[kNumTTYs];
152extern tty gSlaveTTYs[kNumTTYs];
153extern tty_settings gTTYSettings[kNumTTYs];
154
155extern device_hooks gMasterTTYHooks;
156extern device_hooks gSlaveTTYHooks;
157
158extern struct mutex gGlobalTTYLock;
159extern struct mutex gTTYCookieLock;
160extern struct recursive_lock gTTYRequestLock;
161
162
163// functions available for master/slave TTYs
164
165extern int32 get_tty_index(const char *name);
166extern void reset_tty(struct tty *tty, int32 index, mutex* lock, bool isMaster);
167extern void reset_tty_settings(tty_settings *settings, int32 index);
168//extern status_t tty_input_putc(struct tty *tty, int c);
169extern status_t tty_input_read(tty_cookie *cookie, void *buffer,
170					size_t *_length);
171extern status_t tty_output_getc(struct tty *tty, int *_c);
172extern status_t tty_write_to_tty_master(tty_cookie *sourceCookie,
173					const void *buffer, size_t *_length);
174extern status_t tty_write_to_tty_slave(tty_cookie *sourceCookie,
175					const void *buffer, size_t *_length);
176
177extern status_t init_tty_cookie(tty_cookie *cookie, struct tty *tty,
178					struct tty *otherTTY, uint32 openMode);
179extern void uninit_tty_cookie(tty_cookie *cookie);
180extern void add_tty_cookie(tty_cookie *cookie);
181extern void tty_close_cookie(struct tty_cookie *cookie);
182
183extern status_t tty_open(struct tty *tty, tty_service_func func);
184extern status_t tty_close(struct tty *tty);
185extern status_t tty_ioctl(tty_cookie *cookie, uint32 op, void *buffer,
186					size_t length);
187extern status_t tty_select(tty_cookie *cookie, uint8 event, uint32 ref,
188					selectsync *sync);
189extern status_t tty_deselect(tty_cookie *cookie, uint8 event, selectsync *sync);
190
191extern void tty_add_debugger_commands();
192extern void tty_remove_debugger_commands();
193
194#endif	/* TTY_PRIVATE_H */
195