Added the beginnings of our TTY layer.
After having had a look at our own Terminal code (former MuTerm), I even copied the original mess in /dev/tt/ and /dev/pt/. The /dev/tt/ entries could be created and removed on demand, though, but that can't be done yet. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9041 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -10,3 +10,4 @@ SubInclude OBOS_TOP src add-ons kernel drivers graphics ;
|
||||
SubInclude OBOS_TOP src add-ons kernel drivers misc ;
|
||||
SubInclude OBOS_TOP src add-ons kernel drivers network ;
|
||||
SubInclude OBOS_TOP src add-ons kernel drivers random ;
|
||||
SubInclude OBOS_TOP src add-ons kernel drivers tty ;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
SubDir OBOS_TOP src add-ons kernel drivers tty ;
|
||||
|
||||
UsePrivateHeaders kernel ;
|
||||
|
||||
KernelAddon tty : kernel drivers dev :
|
||||
driver.cpp
|
||||
tty.cpp
|
||||
master.cpp
|
||||
slave.cpp
|
||||
;
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
** Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
|
||||
** Distributed under the terms of the Haiku License.
|
||||
*/
|
||||
|
||||
|
||||
#include "tty_private.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#define TTY_TRACE
|
||||
#ifdef TTY_TRACE
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x)
|
||||
#endif
|
||||
|
||||
#define DRIVER_NAME "tty"
|
||||
|
||||
|
||||
int32 api_version = B_CUR_DRIVER_API_VERSION;
|
||||
|
||||
static char *sDeviceNames[kNumTTYs * 2 + 1];
|
||||
// reserve space for "pt/" and "tt/" entries and the terminating NULL
|
||||
|
||||
|
||||
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"));
|
||||
|
||||
// create driver name array
|
||||
|
||||
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.
|
||||
char buffer[64];
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "pt/%c%x", letter, digit);
|
||||
sDeviceNames[i] = strdup(buffer);
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "tt/%c%x", letter, digit);
|
||||
sDeviceNames[i + kNumTTYs] = strdup(buffer);
|
||||
|
||||
if (++digit > 15)
|
||||
digit = 0, letter++;
|
||||
}
|
||||
|
||||
sDeviceNames[kNumTTYs * 2] = NULL;
|
||||
|
||||
// initialize TTY structures
|
||||
|
||||
memset(gMasterTTYs, 0, kNumTTYs * sizeof(struct tty));
|
||||
memset(gSlaveTTYs, 0, kNumTTYs * sizeof(struct tty));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
uninit_driver(void)
|
||||
{
|
||||
TRACE((DRIVER_NAME ": uninit_driver()\n"));
|
||||
|
||||
for (int32 i = 0; sDeviceNames[i] != NULL; i++)
|
||||
free(sDeviceNames[i]);
|
||||
}
|
||||
|
||||
|
||||
const char **
|
||||
publish_devices(void)
|
||||
{
|
||||
TRACE((DRIVER_NAME ": publish_devices()\n"));
|
||||
return const_cast<const char **>(sDeviceNames);
|
||||
}
|
||||
|
||||
|
||||
device_hooks *
|
||||
find_device(const char *name)
|
||||
{
|
||||
TRACE((DRIVER_NAME ": find_device(\"%s\")\n", name));
|
||||
|
||||
for (uint32 i = 0; sDeviceNames[i] != NULL; i++)
|
||||
if (!strcmp(name, sDeviceNames[i]))
|
||||
return i < kNumTTYs ? &gMasterTTYHooks : &gSlaveTTYHooks;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
** Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
|
||||
** Distributed under the terms of the Haiku License.
|
||||
*/
|
||||
|
||||
|
||||
#include "tty_private.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#define MASTER_TRACE
|
||||
#ifdef MASTER_TRACE
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
struct master_cookie {
|
||||
struct tty *tty;
|
||||
uint32 open_mode;
|
||||
};
|
||||
|
||||
|
||||
struct tty gMasterTTYs[kNumTTYs];
|
||||
|
||||
|
||||
static status_t
|
||||
master_open(const char *name, uint32 flags, void **_cookie)
|
||||
{
|
||||
int32 index = get_tty_index(name);
|
||||
|
||||
if (atomic_or(&gMasterTTYs[index].open_count, 1) != 0) {
|
||||
// we're already open!
|
||||
return B_BUSY;
|
||||
}
|
||||
|
||||
master_cookie *cookie = (master_cookie *)malloc(sizeof(struct master_cookie));
|
||||
if (cookie == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
cookie->tty = &gMasterTTYs[index];
|
||||
*_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));
|
||||
|
||||
atomic_and(&cookie->tty->open_count, 0);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
master_free_cookie(void *_cookie)
|
||||
{
|
||||
free(_cookie);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
master_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
|
||||
{
|
||||
TRACE(("master_ioctl: cookie %p, op %lu, buffer %p, length %lu\n", _cookie, op, buffer, length));
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
master_read(void *_cookie, off_t offset, void *buffer, size_t *_length)
|
||||
{
|
||||
TRACE(("master_read: cookie %p, offset %Ld, buffer %p, length %lu\n", _cookie, offset, buffer, *_length));
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
master_write(void *_cookie, off_t offset, const void *buffer, size_t *_length)
|
||||
{
|
||||
TRACE(("master_write: cookie %p, offset %Ld, buffer %p, length %lu\n", _cookie, offset, buffer, *_length));
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
master_select(void *_cookie, uint8 event, uint32 ref, selectsync *sync)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
master_deselect(void *_cookie, uint8 event, selectsync *sync)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
};
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
** Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
|
||||
** Distributed under the terms of the Haiku License.
|
||||
*/
|
||||
|
||||
|
||||
#include "tty_private.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#define SLAVE_TRACE
|
||||
#ifdef SLAVE_TRACE
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x)
|
||||
#endif
|
||||
|
||||
|
||||
struct slave_cookie {
|
||||
struct tty *tty;
|
||||
uint32 open_mode;
|
||||
};
|
||||
|
||||
|
||||
struct tty gSlaveTTYs[kNumTTYs];
|
||||
|
||||
|
||||
static status_t
|
||||
slave_open(const char *name, uint32 flags, void **_cookie)
|
||||
{
|
||||
int32 index = get_tty_index(name);
|
||||
|
||||
if (gSlaveTTYs[index].open_count == 0)
|
||||
return B_IO_ERROR;
|
||||
|
||||
atomic_add(&gSlaveTTYs[index].open_count, 1);
|
||||
|
||||
slave_cookie *cookie = (slave_cookie *)malloc(sizeof(struct slave_cookie));
|
||||
if (cookie == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
cookie->tty = &gSlaveTTYs[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));
|
||||
|
||||
atomic_add(&cookie->tty->open_count, -1);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
slave_free_cookie(void *_cookie)
|
||||
{
|
||||
free(_cookie);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
slave_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
|
||||
{
|
||||
TRACE(("slave_ioctl: cookie %p, op %lu, buffer %p, length %lu\n", _cookie, op, buffer, length));
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
slave_read(void *_cookie, off_t offset, void *buffer, size_t *_length)
|
||||
{
|
||||
TRACE(("slave_read: cookie %p, offset %Ld, buffer %p, length %lu\n", _cookie, offset, buffer, *_length));
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
slave_write(void *_cookie, off_t offset, const void *buffer, size_t *_length)
|
||||
{
|
||||
TRACE(("slave_write: cookie %p, offset %Ld, buffer %p, length %lu\n", _cookie, offset, buffer, *_length));
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
slave_select(void *_cookie, uint8 event, uint32 ref, selectsync *sync)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
slave_deselect(void *_cookie, uint8 event, selectsync *sync)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
** Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
|
||||
** Distributed under the terms of the Haiku License.
|
||||
*/
|
||||
|
||||
|
||||
#include "tty_private.h"
|
||||
|
||||
|
||||
#define TTY_TRACE
|
||||
#ifdef TTY_TRACE
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
int32
|
||||
get_tty_index(const char *name)
|
||||
{
|
||||
// device names follow this form: "pt/%c%x"
|
||||
int8 digit = name[4];
|
||||
if (digit >= 'a')
|
||||
digit -= 'a';
|
||||
else
|
||||
digit -= '0';
|
||||
|
||||
return (name[3] - 'p') * digit;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
** Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
|
||||
** Distributed under the terms of the Haiku License.
|
||||
*/
|
||||
#ifndef TTY_PRIVATE_H
|
||||
#define TTY_PRIVATE_H
|
||||
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <Drivers.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
|
||||
struct tty {
|
||||
int32 open_count;
|
||||
};
|
||||
|
||||
static const uint32 kNumTTYs = 64;
|
||||
|
||||
extern tty gMasterTTYs[kNumTTYs];
|
||||
extern tty gSlaveTTYs[kNumTTYs];
|
||||
|
||||
extern device_hooks gMasterTTYHooks;
|
||||
extern device_hooks gSlaveTTYHooks;
|
||||
|
||||
|
||||
extern int32 get_tty_index(const char *name);
|
||||
|
||||
#endif /* TTY_PRIVATE_H */
|
||||
Reference in New Issue
Block a user