BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / drivers / tty / master.cpp
blobb91b61d2cf01ef784adbd8738fa3ab5975ef68bc
1 /*
2 ** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 ** Distributed under the terms of the Haiku License.
4 */
7 #include "tty_private.h"
9 #include <stdlib.h>
10 #include <string.h>
11 #include <util/AutoLock.h>
14 //#define MASTER_TRACE
15 #ifdef MASTER_TRACE
16 # define TRACE(x) dprintf x
17 #else
18 # define TRACE(x) ;
19 #endif
22 struct master_cookie : tty_cookie {
26 struct tty gMasterTTYs[kNumTTYs];
29 static status_t
30 master_service(struct tty *tty, uint32 op)
32 // nothing here yet
33 return B_OK;
37 static status_t
38 create_master_cookie(master_cookie *&cookie, struct tty *master,
39 struct tty *slave, uint32 openMode)
41 cookie = (master_cookie*)malloc(sizeof(struct master_cookie));
42 if (cookie == NULL)
43 return B_NO_MEMORY;
45 status_t error = init_tty_cookie(cookie, master, slave, openMode);
46 if (error != B_OK) {
47 free(cookie);
48 return error;
51 return B_OK;
55 // #pragma mark -
58 static status_t
59 master_open(const char *name, uint32 flags, void **_cookie)
61 bool findUnusedTTY = strcmp(name, "ptmx") == 0;
63 int32 index = -1;
64 if (!findUnusedTTY) {
65 index = get_tty_index(name);
66 if (index >= (int32)kNumTTYs)
67 return B_ERROR;
70 TRACE(("master_open: TTY index = %ld (name = %s)\n", index, name));
72 MutexLocker globalLocker(gGlobalTTYLock);
74 if (findUnusedTTY) {
75 for (index = 0; index < (int32)kNumTTYs; index++) {
76 if (gMasterTTYs[index].ref_count == 0)
77 break;
79 if (index >= (int32)kNumTTYs)
80 return ENOENT;
81 } else if (gMasterTTYs[index].ref_count > 0) {
82 // we're already open!
83 return B_BUSY;
86 status_t status = tty_open(&gMasterTTYs[index], &master_service);
87 if (status < B_OK) {
88 // initializing TTY failed
89 return status;
92 master_cookie *cookie;
93 status = create_master_cookie(cookie, &gMasterTTYs[index],
94 &gSlaveTTYs[index], flags);
95 if (status != B_OK) {
96 tty_close(&gMasterTTYs[index]);
97 return status;
100 add_tty_cookie(cookie);
102 *_cookie = cookie;
104 return B_OK;
108 static status_t
109 master_close(void *_cookie)
111 master_cookie *cookie = (master_cookie *)_cookie;
113 TRACE(("master_close: cookie %p\n", _cookie));
115 MutexLocker globalLocker(gGlobalTTYLock);
117 // close all connected slave cookies first
118 while (tty_cookie *slave = cookie->other_tty->cookies.Head())
119 tty_close_cookie(slave);
121 // close the client cookie
122 tty_close_cookie(cookie);
124 return B_OK;
128 static status_t
129 master_free_cookie(void *_cookie)
131 // The TTY is already closed. We only have to free the cookie.
132 master_cookie *cookie = (master_cookie *)_cookie;
134 MutexLocker globalLocker(gGlobalTTYLock);
135 uninit_tty_cookie(cookie);
136 globalLocker.Unlock();
138 free(cookie);
140 return B_OK;
144 static status_t
145 master_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
147 master_cookie *cookie = (master_cookie *)_cookie;
149 TRACE(("master_ioctl: cookie %p, op %lu, buffer %p, length %lu\n", _cookie, op, buffer, length));
151 return tty_ioctl(cookie, op, buffer, length);
155 static status_t
156 master_read(void *_cookie, off_t offset, void *buffer, size_t *_length)
158 master_cookie *cookie = (master_cookie *)_cookie;
160 TRACE(("master_read: cookie %p, offset %Ld, buffer %p, length %lu\n",
161 _cookie, offset, buffer, *_length));
163 status_t result = tty_input_read(cookie, buffer, _length);
165 TRACE(("master_read done: cookie %p, result: %lx, length %lu\n", _cookie,
166 result, *_length));
168 return result;
172 static status_t
173 master_write(void *_cookie, off_t offset, const void *buffer, size_t *_length)
175 master_cookie *cookie = (master_cookie *)_cookie;
177 TRACE(("master_write: cookie %p, offset %Ld, buffer %p, length %lu\n",
178 _cookie, offset, buffer, *_length));
180 status_t result = tty_write_to_tty_master(cookie, buffer, _length);
182 TRACE(("master_write done: cookie %p, result: %lx, length %lu\n", _cookie,
183 result, *_length));
185 return result;
189 static status_t
190 master_select(void *_cookie, uint8 event, uint32 ref, selectsync *sync)
192 master_cookie *cookie = (master_cookie *)_cookie;
194 return tty_select(cookie, event, ref, sync);
198 static status_t
199 master_deselect(void *_cookie, uint8 event, selectsync *sync)
201 master_cookie *cookie = (master_cookie *)_cookie;
203 return tty_deselect(cookie, event, sync);
207 device_hooks gMasterTTYHooks = {
208 &master_open,
209 &master_close,
210 &master_free_cookie,
211 &master_ioctl,
212 &master_read,
213 &master_write,
214 &master_select,
215 &master_deselect,
216 NULL, // read_pages()
217 NULL // write_pages()