* Copyright 2004, Axel DΓΆrfler, axeld@pinc-software.de. 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"
#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];
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));
recursive_lock_init(&gTTYRequestLock, "tty requests");
mutex_init(&gGlobalTTYLock, "tty global");
mutex_init(&gTTYCookieLock, "tty cookies");
char letter = 'p';
int8 digit = 0;
for (uint32 i = 0; i < kNumTTYs; i++) {
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)
{
int8 digit = name[4];
if (digit >= 'a') {
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;
}