Delete the old TTY driver.
No longer used or included in the build after the previous commit.
This commit is contained in:
@@ -1,18 +0,0 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel drivers tty ;
|
||||
|
||||
UsePrivateKernelHeaders ;
|
||||
UsePrivateHeaders drivers ;
|
||||
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel generic tty ] ;
|
||||
|
||||
KernelAddon <driver>tty :
|
||||
driver.cpp
|
||||
tty.cpp
|
||||
line_buffer.cpp
|
||||
master.cpp
|
||||
slave.cpp
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles line_buffer.cpp ]
|
||||
+= [ FDirName $(HAIKU_TOP) src add-ons kernel generic tty ] ;
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <lock.h>
|
||||
|
||||
#include "tty_driver.h"
|
||||
#include "tty_private.h"
|
||||
|
||||
|
||||
//#define TTY_TRACE
|
||||
#ifdef TTY_TRACE
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x)
|
||||
#endif
|
||||
|
||||
#define DRIVER_NAME "tty"
|
||||
|
||||
static const int kMaxCachedSemaphores = 8;
|
||||
|
||||
int32 api_version = B_CUR_DRIVER_API_VERSION;
|
||||
|
||||
char *gDeviceNames[kNumTTYs * 2 + 3];
|
||||
// reserve space for "pt/" and "tt/" entries, "ptmx", "tty", and the
|
||||
// terminating NULL
|
||||
|
||||
static mutex sTTYLocks[kNumTTYs];
|
||||
static tty_settings sTTYSettings[kNumTTYs];
|
||||
|
||||
struct mutex gGlobalTTYLock;
|
||||
struct mutex gTTYCookieLock;
|
||||
struct recursive_lock gTTYRequestLock;
|
||||
|
||||
|
||||
status_t
|
||||
init_hardware(void)
|
||||
{
|
||||
TRACE((DRIVER_NAME ": init_hardware()\n"));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
init_driver(void)
|
||||
{
|
||||
TRACE((DRIVER_NAME ": init_driver()\n"));
|
||||
|
||||
memset(gDeviceNames, 0, sizeof(gDeviceNames));
|
||||
|
||||
// create the request mutex
|
||||
recursive_lock_init(&gTTYRequestLock, "tty requests");
|
||||
|
||||
// create the global mutex
|
||||
mutex_init(&gGlobalTTYLock, "tty global");
|
||||
|
||||
// create the cookie mutex
|
||||
mutex_init(&gTTYCookieLock, "tty cookies");
|
||||
|
||||
// create driver name array and initialize basic TTY structures
|
||||
|
||||
char letter = 'p';
|
||||
int8 digit = 0;
|
||||
|
||||
for (uint32 i = 0; i < kNumTTYs; i++) {
|
||||
// For compatibility, we have to create the same mess in /dev/pt and
|
||||
// /dev/tt as BeOS does: we publish devices p0, p1, ..., pf, r1, ...,
|
||||
// sf. It would be nice if we could drop compatibility and create
|
||||
// something better. In fact we already don't need the master devices
|
||||
// anymore, since "/dev/ptmx" does the job. The slaves entries could
|
||||
// be published on the fly when a master is opened (e.g via
|
||||
// vfs_create_special_node()).
|
||||
char buffer[64];
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "pt/%c%x", letter, digit);
|
||||
gDeviceNames[i] = strdup(buffer);
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "tt/%c%x", letter, digit);
|
||||
gDeviceNames[i + kNumTTYs] = strdup(buffer);
|
||||
|
||||
if (++digit > 15)
|
||||
digit = 0, letter++;
|
||||
|
||||
mutex_init(&sTTYLocks[i], "tty lock");
|
||||
reset_tty(&gMasterTTYs[i], i, &sTTYLocks[i], true);
|
||||
reset_tty(&gSlaveTTYs[i], i, &sTTYLocks[i], false);
|
||||
reset_tty_settings(&sTTYSettings[i]);
|
||||
|
||||
if (!gDeviceNames[i] || !gDeviceNames[i + kNumTTYs]) {
|
||||
uninit_driver();
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
gDeviceNames[2 * kNumTTYs] = (char *)"ptmx";
|
||||
gDeviceNames[2 * kNumTTYs + 1] = (char *)"tty";
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
uninit_driver(void)
|
||||
{
|
||||
TRACE((DRIVER_NAME ": uninit_driver()\n"));
|
||||
|
||||
for (int32 i = 0; i < (int32)kNumTTYs * 2; i++)
|
||||
free(gDeviceNames[i]);
|
||||
|
||||
for (int32 i = 0; i < (int32)kNumTTYs; i++)
|
||||
mutex_destroy(&sTTYLocks[i]);
|
||||
|
||||
recursive_lock_destroy(&gTTYRequestLock);
|
||||
mutex_destroy(&gTTYCookieLock);
|
||||
mutex_destroy(&gGlobalTTYLock);
|
||||
}
|
||||
|
||||
|
||||
const char **
|
||||
publish_devices(void)
|
||||
{
|
||||
TRACE((DRIVER_NAME ": publish_devices()\n"));
|
||||
return const_cast<const char **>(gDeviceNames);
|
||||
}
|
||||
|
||||
|
||||
device_hooks *
|
||||
find_device(const char *name)
|
||||
{
|
||||
TRACE((DRIVER_NAME ": find_device(\"%s\")\n", name));
|
||||
|
||||
for (uint32 i = 0; gDeviceNames[i] != NULL; i++)
|
||||
if (!strcmp(name, gDeviceNames[i])) {
|
||||
return i < kNumTTYs || i == (2 * kNumTTYs)
|
||||
? &gMasterTTYHooks : &gSlaveTTYHooks;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
get_tty_index(const char* name)
|
||||
{
|
||||
// device names follow this form: "pt/%c%x"
|
||||
int8 digit = name[4];
|
||||
if (digit >= 'a') {
|
||||
// hexadecimal digits
|
||||
digit -= 'a' - 10;
|
||||
} else
|
||||
digit -= '0';
|
||||
|
||||
return (name[3] - 'p') * 16 + digit;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
reset_tty(struct tty* tty, int32 index, mutex* lock, bool isMaster)
|
||||
{
|
||||
tty->ref_count = 0;
|
||||
tty->open_count = 0;
|
||||
tty->opened_count = 0;
|
||||
tty->index = index;
|
||||
tty->lock = lock;
|
||||
tty->settings = &sTTYSettings[index];
|
||||
tty->select_pool = NULL;
|
||||
tty->is_master = isMaster;
|
||||
tty->pending_eof = 0;
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
** Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
|
||||
** Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "tty_driver.h"
|
||||
#include "tty_private.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <util/AutoLock.h>
|
||||
|
||||
|
||||
//#define MASTER_TRACE
|
||||
#ifdef MASTER_TRACE
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
struct master_cookie : tty_cookie {
|
||||
};
|
||||
|
||||
|
||||
struct tty gMasterTTYs[kNumTTYs];
|
||||
|
||||
|
||||
static status_t
|
||||
master_service(struct tty *tty, uint32 op)
|
||||
{
|
||||
// nothing here yet
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
create_master_cookie(master_cookie *&cookie, struct tty *master,
|
||||
struct tty *slave, uint32 openMode)
|
||||
{
|
||||
cookie = (master_cookie*)malloc(sizeof(struct master_cookie));
|
||||
if (cookie == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = init_tty_cookie(cookie, master, slave, openMode);
|
||||
if (error != B_OK) {
|
||||
free(cookie);
|
||||
return error;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
static status_t
|
||||
master_open(const char *name, uint32 flags, void **_cookie)
|
||||
{
|
||||
bool findUnusedTTY = strcmp(name, "ptmx") == 0;
|
||||
|
||||
int32 index = -1;
|
||||
if (!findUnusedTTY) {
|
||||
index = get_tty_index(name);
|
||||
if (index >= (int32)kNumTTYs)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
TRACE(("master_open: TTY index = %" B_PRId32 " (name = %s)\n", index,
|
||||
name));
|
||||
|
||||
MutexLocker globalLocker(gGlobalTTYLock);
|
||||
|
||||
if (findUnusedTTY) {
|
||||
for (index = 0; index < (int32)kNumTTYs; index++) {
|
||||
if (gMasterTTYs[index].ref_count == 0)
|
||||
break;
|
||||
}
|
||||
if (index >= (int32)kNumTTYs)
|
||||
return ENOENT;
|
||||
} else if (gMasterTTYs[index].ref_count > 0) {
|
||||
// we're already open!
|
||||
return B_BUSY;
|
||||
}
|
||||
|
||||
gMasterTTYs[index].opened_count = 0;
|
||||
gSlaveTTYs[index].opened_count = 0;
|
||||
status_t status = tty_open(&gMasterTTYs[index], &master_service);
|
||||
if (status < B_OK) {
|
||||
// initializing TTY failed
|
||||
return status;
|
||||
}
|
||||
|
||||
master_cookie *cookie;
|
||||
status = create_master_cookie(cookie, &gMasterTTYs[index],
|
||||
&gSlaveTTYs[index], flags);
|
||||
if (status != B_OK) {
|
||||
tty_close(&gMasterTTYs[index]);
|
||||
return status;
|
||||
}
|
||||
|
||||
*_cookie = cookie;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
master_close(void *_cookie)
|
||||
{
|
||||
master_cookie *cookie = (master_cookie *)_cookie;
|
||||
|
||||
TRACE(("master_close: cookie %p\n", _cookie));
|
||||
|
||||
MutexLocker globalLocker(gGlobalTTYLock);
|
||||
|
||||
// close all connected slave cookies first
|
||||
while (tty_cookie *slave = cookie->other_tty->cookies.Head())
|
||||
tty_close_cookie(slave);
|
||||
|
||||
// close the client cookie
|
||||
tty_close_cookie(cookie);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
master_free_cookie(void *_cookie)
|
||||
{
|
||||
// The TTY is already closed. We only have to free the cookie.
|
||||
master_cookie *cookie = (master_cookie *)_cookie;
|
||||
|
||||
MutexLocker globalLocker(gGlobalTTYLock);
|
||||
uninit_tty_cookie(cookie);
|
||||
globalLocker.Unlock();
|
||||
|
||||
free(cookie);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
master_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
|
||||
{
|
||||
master_cookie *cookie = (master_cookie *)_cookie;
|
||||
|
||||
TRACE(("master_ioctl: cookie %p, op %" B_PRIu32 ", buffer %p, length %lu"
|
||||
"\n", _cookie, op, buffer, length));
|
||||
|
||||
return tty_ioctl(cookie, op, buffer, length);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
master_read(void *_cookie, off_t offset, void *buffer, size_t *_length)
|
||||
{
|
||||
master_cookie *cookie = (master_cookie *)_cookie;
|
||||
|
||||
TRACE(("master_read: cookie %p, offset %" B_PRIdOFF ", buffer %p, length "
|
||||
"%lu\n", _cookie, offset, buffer, *_length));
|
||||
|
||||
status_t result = tty_input_read(cookie, buffer, _length);
|
||||
|
||||
TRACE(("master_read done: cookie %p, result: %" B_PRIx32 ", length %lu\n",
|
||||
_cookie, result, *_length));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
master_write(void *_cookie, off_t offset, const void *buffer, size_t *_length)
|
||||
{
|
||||
master_cookie *cookie = (master_cookie *)_cookie;
|
||||
|
||||
TRACE(("master_write: cookie %p, offset %" B_PRIdOFF ", buffer %p, length "
|
||||
"%lu\n", _cookie, offset, buffer, *_length));
|
||||
|
||||
status_t result = tty_write_to_tty_master(cookie, buffer, _length);
|
||||
|
||||
TRACE(("master_write done: cookie %p, result: %" B_PRIx32 ", length %lu\n",
|
||||
_cookie, result, *_length));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
master_select(void *_cookie, uint8 event, uint32 ref, selectsync *sync)
|
||||
{
|
||||
master_cookie *cookie = (master_cookie *)_cookie;
|
||||
|
||||
return tty_select(cookie, event, ref, sync);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
master_deselect(void *_cookie, uint8 event, selectsync *sync)
|
||||
{
|
||||
master_cookie *cookie = (master_cookie *)_cookie;
|
||||
|
||||
return tty_deselect(cookie, event, sync);
|
||||
}
|
||||
|
||||
|
||||
device_hooks gMasterTTYHooks = {
|
||||
&master_open,
|
||||
&master_close,
|
||||
&master_free_cookie,
|
||||
&master_ioctl,
|
||||
&master_read,
|
||||
&master_write,
|
||||
&master_select,
|
||||
&master_deselect,
|
||||
NULL, // read_pages()
|
||||
NULL // write_pages()
|
||||
};
|
||||
@@ -1,232 +0,0 @@
|
||||
/*
|
||||
** Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
|
||||
** Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <util/AutoLock.h>
|
||||
|
||||
#include <team.h>
|
||||
|
||||
#include "tty_driver.h"
|
||||
#include "tty_private.h"
|
||||
|
||||
|
||||
//#define SLAVE_TRACE
|
||||
#ifdef SLAVE_TRACE
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x)
|
||||
#endif
|
||||
|
||||
|
||||
struct slave_cookie : tty_cookie {
|
||||
};
|
||||
|
||||
|
||||
struct tty gSlaveTTYs[kNumTTYs];
|
||||
|
||||
|
||||
static status_t
|
||||
slave_open(const char *name, uint32 flags, void **_cookie)
|
||||
{
|
||||
// Get the tty index: Opening "/dev/tty" means opening the process'
|
||||
// controlling tty.
|
||||
int32 index = get_tty_index(name);
|
||||
if (strcmp(name, "tty") == 0) {
|
||||
index = team_get_controlling_tty();
|
||||
if (index < 0)
|
||||
return B_NOT_ALLOWED;
|
||||
} else {
|
||||
index = get_tty_index(name);
|
||||
if (index >= (int32)kNumTTYs)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
TRACE(("slave_open: TTY index = %" B_PRId32 " (name = %s)\n", index,
|
||||
name));
|
||||
|
||||
MutexLocker globalLocker(gGlobalTTYLock);
|
||||
|
||||
// we may only be used if our master has already been opened
|
||||
if (gMasterTTYs[index].open_count == 0)
|
||||
return B_IO_ERROR;
|
||||
|
||||
bool makeControllingTTY = (flags & O_NOCTTY) == 0;
|
||||
pid_t processID = getpid();
|
||||
pid_t sessionID = getsid(processID);
|
||||
|
||||
if (gSlaveTTYs[index].open_count == 0) {
|
||||
// We only allow session leaders to open the tty initially.
|
||||
if (makeControllingTTY && processID != sessionID)
|
||||
return B_NOT_ALLOWED;
|
||||
|
||||
status_t status = tty_open(&gSlaveTTYs[index], NULL);
|
||||
if (status < B_OK) {
|
||||
// initializing TTY failed
|
||||
return status;
|
||||
}
|
||||
} else if (makeControllingTTY) {
|
||||
// If already open, we allow only processes from the same session
|
||||
// to open the tty again while becoming controlling tty
|
||||
pid_t ttySession = gSlaveTTYs[index].settings->session_id;
|
||||
if (ttySession >= 0) {
|
||||
makeControllingTTY = false;
|
||||
} else {
|
||||
// The tty is not associated with a session yet. The process needs
|
||||
// to be a session leader.
|
||||
if (makeControllingTTY && processID != sessionID)
|
||||
return B_NOT_ALLOWED;
|
||||
}
|
||||
}
|
||||
|
||||
slave_cookie *cookie = (slave_cookie *)malloc(sizeof(struct slave_cookie));
|
||||
if (cookie == NULL) {
|
||||
if (gSlaveTTYs[index].open_count == 0)
|
||||
tty_close(&gSlaveTTYs[index]);
|
||||
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
status_t status = init_tty_cookie(cookie, &gSlaveTTYs[index],
|
||||
&gMasterTTYs[index], flags);
|
||||
if (status != B_OK) {
|
||||
free(cookie);
|
||||
|
||||
if (gSlaveTTYs[index].open_count == 0)
|
||||
tty_close(&gSlaveTTYs[index]);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if (gSlaveTTYs[index].open_count == 0) {
|
||||
gSlaveTTYs[index].lock = gMasterTTYs[index].lock;
|
||||
gSlaveTTYs[index].settings->session_id = -1;
|
||||
gSlaveTTYs[index].settings->pgrp_id = -1;
|
||||
}
|
||||
|
||||
if (makeControllingTTY) {
|
||||
gSlaveTTYs[index].settings->session_id = sessionID;
|
||||
gSlaveTTYs[index].settings->pgrp_id = sessionID;
|
||||
team_set_controlling_tty(gSlaveTTYs[index].index);
|
||||
}
|
||||
|
||||
*_cookie = cookie;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
slave_close(void *_cookie)
|
||||
{
|
||||
slave_cookie *cookie = (slave_cookie *)_cookie;
|
||||
|
||||
TRACE(("slave_close: cookie %p\n", _cookie));
|
||||
|
||||
MutexLocker globalLocker(gGlobalTTYLock);
|
||||
|
||||
// unblock and wait for all blocking operations
|
||||
tty_close_cookie(cookie);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
slave_free_cookie(void *_cookie)
|
||||
{
|
||||
// The TTY is already closed. We only have to free the cookie.
|
||||
slave_cookie *cookie = (slave_cookie *)_cookie;
|
||||
|
||||
TRACE(("slave_free_cookie: cookie %p\n", _cookie));
|
||||
|
||||
MutexLocker globalLocker(gGlobalTTYLock);
|
||||
uninit_tty_cookie(cookie);
|
||||
globalLocker.Unlock();
|
||||
|
||||
free(cookie);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
slave_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
|
||||
{
|
||||
slave_cookie *cookie = (slave_cookie *)_cookie;
|
||||
|
||||
TRACE(("slave_ioctl: cookie %p, op %" B_PRIu32 ", buffer %p, length %lu\n",
|
||||
_cookie, op, buffer, length));
|
||||
|
||||
return tty_ioctl(cookie, op, buffer, length);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
slave_read(void *_cookie, off_t offset, void *buffer, size_t *_length)
|
||||
{
|
||||
slave_cookie *cookie = (slave_cookie *)_cookie;
|
||||
|
||||
TRACE(("slave_read: cookie %p, offset %" B_PRIdOFF ", buffer %p, length "
|
||||
"%lu\n", _cookie, offset, buffer, *_length));
|
||||
|
||||
status_t result = tty_input_read(cookie, buffer, _length);
|
||||
|
||||
TRACE(("slave_read done: cookie %p, result %" B_PRIx32 ", length %lu\n",
|
||||
_cookie, result, *_length));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
slave_write(void *_cookie, off_t offset, const void *buffer, size_t *_length)
|
||||
{
|
||||
slave_cookie *cookie = (slave_cookie *)_cookie;
|
||||
|
||||
TRACE(("slave_write: cookie %p, offset %" B_PRIdOFF", buffer %p, length "
|
||||
"%lu\n", _cookie, offset, buffer, *_length));
|
||||
|
||||
status_t result = tty_write_to_tty_slave(cookie, buffer, _length);
|
||||
|
||||
TRACE(("slave_write done: cookie %p, result %" B_PRIx32 ", length %lu\n",
|
||||
_cookie, result, *_length));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
slave_select(void *_cookie, uint8 event, uint32 ref, selectsync *sync)
|
||||
{
|
||||
slave_cookie *cookie = (slave_cookie *)_cookie;
|
||||
|
||||
return tty_select(cookie, event, ref, sync);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
slave_deselect(void *_cookie, uint8 event, selectsync *sync)
|
||||
{
|
||||
slave_cookie *cookie = (slave_cookie *)_cookie;
|
||||
|
||||
return tty_deselect(cookie, event, sync);
|
||||
}
|
||||
|
||||
|
||||
device_hooks gSlaveTTYHooks = {
|
||||
&slave_open,
|
||||
&slave_close,
|
||||
&slave_free_cookie,
|
||||
&slave_ioctl,
|
||||
&slave_read,
|
||||
&slave_write,
|
||||
&slave_select,
|
||||
&slave_deselect,
|
||||
NULL, // read_pages()
|
||||
NULL // write_pages()
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2006, Axel Dörfler, [email protected]. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TTY_DRIVER_H
|
||||
#define TTY_DRIVER_H
|
||||
|
||||
|
||||
#include "tty_private.h"
|
||||
|
||||
|
||||
extern tty gMasterTTYs[kNumTTYs];
|
||||
extern tty gSlaveTTYs[kNumTTYs];
|
||||
|
||||
extern device_hooks gMasterTTYHooks;
|
||||
extern device_hooks gSlaveTTYHooks;
|
||||
|
||||
extern struct mutex gGlobalTTYLock;
|
||||
|
||||
extern int32 get_tty_index(const char *name);
|
||||
|
||||
extern void reset_tty(struct tty *tty, int32 index, mutex* lock, bool isMaster);
|
||||
|
||||
|
||||
#endif /* !TTY_DRIVER_H */
|
||||
@@ -1,178 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2006, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TTY_PRIVATE_H
|
||||
#define TTY_PRIVATE_H
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
#include <Drivers.h>
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <condition_variable.h>
|
||||
#include <fs/select_sync_pool.h>
|
||||
#include <lock.h>
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
#include "line_buffer.h"
|
||||
|
||||
|
||||
#define TTY_BUFFER_SIZE 4096
|
||||
|
||||
// The only nice Rico'ism :)
|
||||
#define CTRL(c) ((c) - 0100)
|
||||
|
||||
|
||||
typedef status_t (*tty_service_func)(struct tty *tty, uint32 op);
|
||||
// not yet used...
|
||||
|
||||
|
||||
class RequestOwner;
|
||||
class Semaphore;
|
||||
struct tty;
|
||||
struct tty_cookie;
|
||||
|
||||
class Request : public DoublyLinkedListLinkImpl<Request> {
|
||||
public:
|
||||
Request();
|
||||
|
||||
void Init(RequestOwner *owner, tty_cookie *cookie, size_t bytesNeeded);
|
||||
|
||||
tty_cookie *TTYCookie() const { return fCookie; }
|
||||
|
||||
void Notify(size_t bytesAvailable);
|
||||
void NotifyError(status_t error);
|
||||
|
||||
bool WasNotified() const { return fNotified; }
|
||||
bool HasError() const { return fError; }
|
||||
|
||||
void Dump(const char* prefix);
|
||||
|
||||
private:
|
||||
RequestOwner *fOwner;
|
||||
tty_cookie *fCookie;
|
||||
size_t fBytesNeeded;
|
||||
bool fNotified;
|
||||
bool fError;
|
||||
};
|
||||
|
||||
class RequestQueue {
|
||||
public:
|
||||
RequestQueue();
|
||||
~RequestQueue() {}
|
||||
|
||||
void Add(Request *request);
|
||||
void Remove(Request *request);
|
||||
|
||||
Request *First() const { return fRequests.First(); }
|
||||
bool IsEmpty() const { return fRequests.IsEmpty(); }
|
||||
|
||||
void NotifyFirst(size_t bytesAvailable);
|
||||
void NotifyError(status_t error);
|
||||
void NotifyError(tty_cookie *cookie, status_t error);
|
||||
|
||||
void Dump(const char* prefix);
|
||||
|
||||
private:
|
||||
typedef DoublyLinkedList<Request> RequestList;
|
||||
|
||||
RequestList fRequests;
|
||||
};
|
||||
|
||||
class RequestOwner {
|
||||
public:
|
||||
RequestOwner();
|
||||
|
||||
void Enqueue(tty_cookie *cookie, RequestQueue *queue1,
|
||||
RequestQueue *queue2 = NULL);
|
||||
void Dequeue();
|
||||
|
||||
void SetBytesNeeded(size_t bytesNeeded);
|
||||
size_t BytesNeeded() const { return fBytesNeeded; }
|
||||
|
||||
status_t Wait(bool interruptable, bigtime_t timeout = B_INFINITE_TIMEOUT);
|
||||
|
||||
bool IsFirstInQueues();
|
||||
|
||||
void Notify(Request *request);
|
||||
void NotifyError(Request *request, status_t error);
|
||||
|
||||
status_t Error() const { return fError; }
|
||||
|
||||
private:
|
||||
ConditionVariable* fConditionVariable;
|
||||
tty_cookie* fCookie;
|
||||
status_t fError;
|
||||
RequestQueue* fRequestQueues[2];
|
||||
Request fRequests[2];
|
||||
size_t fBytesNeeded;
|
||||
};
|
||||
|
||||
|
||||
struct tty_cookie : DoublyLinkedListLinkImpl<tty_cookie> {
|
||||
struct tty *tty;
|
||||
struct tty *other_tty;
|
||||
uint32 open_mode;
|
||||
int32 thread_count;
|
||||
sem_id blocking_semaphore;
|
||||
bool closed;
|
||||
};
|
||||
|
||||
typedef DoublyLinkedList<tty_cookie> TTYCookieList;
|
||||
|
||||
struct tty_settings {
|
||||
pid_t pgrp_id;
|
||||
pid_t session_id;
|
||||
struct termios termios;
|
||||
struct winsize window_size;
|
||||
};
|
||||
|
||||
struct tty {
|
||||
int32 ref_count; // referenced by cookies
|
||||
int32 open_count;
|
||||
int32 opened_count;
|
||||
select_sync_pool* select_pool;
|
||||
RequestQueue reader_queue;
|
||||
RequestQueue writer_queue;
|
||||
TTYCookieList cookies;
|
||||
line_buffer input_buffer;
|
||||
tty_service_func service_func;
|
||||
uint32 pending_eof;
|
||||
bool is_master;
|
||||
struct mutex* lock;
|
||||
tty_settings* settings;
|
||||
int32 index;
|
||||
};
|
||||
|
||||
static const uint32 kNumTTYs = 64;
|
||||
|
||||
extern char *gDeviceNames[kNumTTYs * 2 + 3];
|
||||
|
||||
extern struct mutex gTTYCookieLock;
|
||||
extern struct recursive_lock gTTYRequestLock;
|
||||
|
||||
extern status_t tty_open(struct tty *tty, tty_service_func func);
|
||||
extern status_t tty_close(struct tty *tty);
|
||||
|
||||
extern status_t init_tty_cookie(tty_cookie *cookie, struct tty *tty,
|
||||
struct tty *otherTTY, uint32 openMode);
|
||||
extern void uninit_tty_cookie(tty_cookie *cookie);
|
||||
extern void tty_close_cookie(struct tty_cookie *cookie);
|
||||
|
||||
// functions available for master/slave TTYs
|
||||
extern void reset_tty_settings(tty_settings *settings);
|
||||
|
||||
extern status_t tty_input_read(tty_cookie *cookie, void *buffer,
|
||||
size_t *_length);
|
||||
extern status_t tty_write_to_tty_master(tty_cookie *sourceCookie,
|
||||
const void *buffer, size_t *_length);
|
||||
extern status_t tty_write_to_tty_slave(tty_cookie *sourceCookie,
|
||||
const void *buffer, size_t *_length);
|
||||
extern status_t tty_ioctl(tty_cookie *cookie, uint32 op, void *buffer,
|
||||
size_t length);
|
||||
extern status_t tty_select(tty_cookie *cookie, uint8 event, uint32 ref,
|
||||
selectsync *sync);
|
||||
extern status_t tty_deselect(tty_cookie *cookie, uint8 event, selectsync *sync);
|
||||
|
||||
#endif /* TTY_PRIVATE_H */
|
||||
Reference in New Issue
Block a user