Author: axeld Date: 2009-11-19 23:00:24 +0100 (Thu, 19 Nov 2009) New Revision: 34142 Changeset: http://dev.haiku-os.org/changeset/34142/haiku Modified: haiku/trunk/src/add-ons/kernel/drivers/tty/tty.cpp Log: * Cleanup, no functional change. Modified: haiku/trunk/src/add-ons/kernel/drivers/tty/tty.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/drivers/tty/tty.cpp 2009-11-19 21:51:36 UTC (rev 34141) +++ haiku/trunk/src/add-ons/kernel/drivers/tty/tty.cpp 2009-11-19 22:00:24 UTC (rev 34142) @@ -1,14 +1,17 @@ /* * Copyright 2007-2009, Ingo Weinhold, ingo_weinhold@xxxxxxx - * Copyright 2004-2006, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights reserved. + * Copyright 2004-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx * Distributed under the terms of the MIT License. */ + // This file could be moved into a generic tty module. // The whole hardware signaling stuff is missing, though - it's currently // tailored for pseudo-TTYs. Have a look at Be's TTY includes (drivers/tty/*) +#include "tty_private.h" + #include <ctype.h> #include <errno.h> #include <signal.h> @@ -24,9 +27,7 @@ #include <tty.h> -#include "tty_private.h" - //#define TTY_TRACE #ifdef TTY_TRACE # define TRACE(x) dprintf x @@ -89,92 +90,102 @@ tty_settings gTTYSettings[kNumTTYs]; -static void tty_notify_select_event(struct tty *tty, uint8 event); -static void tty_notify_if_available(struct tty *tty, struct tty *otherTTY, - bool notifySelect); +static void tty_notify_select_event(struct tty* tty, uint8 event); +static void tty_notify_if_available(struct tty* tty, struct tty* otherTTY, + bool notifySelect); class AbstractLocker { - public: - AbstractLocker(tty_cookie *cookie) : fCookie(cookie), fBytes(0) {} +public: + AbstractLocker(tty_cookie* cookie) + : + fCookie(cookie), + fBytes(0) + { + } - size_t AvailableBytes() const { return fBytes; } + size_t AvailableBytes() const + { return fBytes; } - protected: - void Lock() { mutex_lock(fCookie->tty->lock); } - void Unlock() { mutex_unlock(fCookie->tty->lock); } +protected: + void Lock() + { mutex_lock(fCookie->tty->lock); } + void Unlock() + { mutex_unlock(fCookie->tty->lock); } - tty_cookie *fCookie; - size_t fBytes; + tty_cookie* fCookie; + size_t fBytes; }; class WriterLocker : public AbstractLocker { - public: - WriterLocker(tty_cookie *sourceCookie); - ~WriterLocker(); +public: + WriterLocker(tty_cookie* sourceCookie); + ~WriterLocker(); - status_t AcquireWriter(bool dontBlock, size_t bytesNeeded); + status_t AcquireWriter(bool dontBlock, + size_t bytesNeeded); - private: - size_t _CheckAvailableBytes() const; - status_t _CheckBackgroundWrite() const; +private: + size_t _CheckAvailableBytes() const; + status_t _CheckBackgroundWrite() const; - struct tty *fSource; - struct tty *fTarget; - RequestOwner fRequestOwner; - bool fEcho; + struct tty* fSource; + struct tty* fTarget; + RequestOwner fRequestOwner; + bool fEcho; }; class ReaderLocker : public AbstractLocker { - public: - ReaderLocker(tty_cookie *cookie); - ~ReaderLocker(); +public: + ReaderLocker(tty_cookie* cookie); + ~ReaderLocker(); - status_t AcquireReader(bigtime_t timeout, size_t minBytes); - status_t AcquireReader(bool dontBlock); + status_t AcquireReader(bigtime_t timeout, + size_t minBytes); + status_t AcquireReader(bool dontBlock); - private: - size_t _CheckAvailableBytes() const; - status_t _CheckBackgroundRead() const; +private: + size_t _CheckAvailableBytes() const; + status_t _CheckBackgroundRead() const; - struct tty *fTTY; - RequestOwner fRequestOwner; + struct tty* fTTY; + RequestOwner fRequestOwner; }; class TTYReferenceLocking { - public: - inline bool Lock(tty_cookie *cookie) - { - MutexLocker _(gTTYCookieLock); +public: + inline bool Lock(tty_cookie* cookie) + { + MutexLocker _(gTTYCookieLock); - if (cookie->closed) - return false; + if (cookie->closed) + return false; - cookie->thread_count++; + cookie->thread_count++; - return true; - } + return true; + } - inline void Unlock(tty_cookie *cookie) - { - MutexLocker locker(gTTYCookieLock); + inline void Unlock(tty_cookie* cookie) + { + MutexLocker locker(gTTYCookieLock); - sem_id semaphore = -1; - if (--cookie->thread_count == 0 && cookie->closed) - semaphore = cookie->blocking_semaphore; + sem_id semaphore = -1; + if (--cookie->thread_count == 0 && cookie->closed) + semaphore = cookie->blocking_semaphore; - locker.Unlock(); + locker.Unlock(); - if (semaphore >= 0) { - TRACE(("TTYReference: cookie %p closed, last operation done, " - "releasing blocking sem %ld\n", cookie, semaphore)); + if (semaphore >= 0) { + TRACE(("TTYReference: cookie %p closed, last operation done, " + "releasing blocking sem %ld\n", cookie, semaphore)); - release_sem(semaphore); - } + release_sem(semaphore); } + } }; typedef AutoLocker<tty_cookie, TTYReferenceLocking> TTYReference; @@ -195,7 +206,7 @@ void -Request::Init(RequestOwner *owner, tty_cookie *cookie, size_t bytesNeeded) +Request::Init(RequestOwner* owner, tty_cookie* cookie, size_t bytesNeeded) { fOwner = owner; fCookie = cookie; @@ -249,7 +260,7 @@ void -RequestQueue::Add(Request *request) +RequestQueue::Add(Request* request) { if (request) { RecursiveLocker _(gTTYRequestLock); @@ -260,7 +271,7 @@ void -RequestQueue::Remove(Request *request) +RequestQueue::Remove(Request* request) { if (request) { RecursiveLocker _(gTTYRequestLock); @@ -275,7 +286,7 @@ { RecursiveLocker _(gTTYRequestLock); - if (Request *first = First()) + if (Request* first = First()) first->Notify(bytesAvailable); } @@ -286,19 +297,19 @@ RecursiveLocker _(gTTYRequestLock); for (RequestList::Iterator it = fRequests.GetIterator(); it.HasNext();) { - Request *request = it.Next(); + Request* request = it.Next(); request->NotifyError(error); } } void -RequestQueue::NotifyError(tty_cookie *cookie, status_t error) +RequestQueue::NotifyError(tty_cookie* cookie, status_t error) { RecursiveLocker _(gTTYRequestLock); for (RequestList::Iterator it = fRequests.GetIterator(); it.HasNext();) { - Request *request = it.Next(); + Request* request = it.Next(); if (request->TTYCookie() == cookie) request->NotifyError(error); } @@ -329,12 +340,11 @@ } -/** - * The caller must already hold the request lock. - */ +/*! The caller must already hold the request lock. +*/ void -RequestOwner::Enqueue(tty_cookie *cookie, RequestQueue *queue1, - RequestQueue *queue2) +RequestOwner::Enqueue(tty_cookie* cookie, RequestQueue* queue1, + RequestQueue* queue2) { TRACE(("%p->RequestOwner::Enqueue(%p, %p, %p)\n", this, cookie, queue1, queue2)); @@ -358,9 +368,8 @@ } -/** - * The caller must already hold the request lock. - */ +/*! The caller must already hold the request lock. +*/ void RequestOwner::Dequeue() { @@ -387,9 +396,8 @@ } -/** - * The request lock MUST NOT be held! - */ +/*! The request lock MUST NOT be held! +*/ status_t RequestOwner::Wait(bool interruptable, bigtime_t timeout) { @@ -454,7 +462,7 @@ void -RequestOwner::Notify(Request *request) +RequestOwner::Notify(Request* request) { TRACE(("%p->RequestOwner::Notify(%p)\n", this, request)); @@ -476,7 +484,7 @@ void -RequestOwner::NotifyError(Request *request, status_t error) +RequestOwner::NotifyError(Request* request, status_t error) { TRACE(("%p->RequestOwner::NotifyError(%p, %lx)\n", this, request, error)); @@ -494,8 +502,9 @@ // #pragma mark - -WriterLocker::WriterLocker(tty_cookie *sourceCookie) - : AbstractLocker(sourceCookie), +WriterLocker::WriterLocker(tty_cookie* sourceCookie) + : + AbstractLocker(sourceCookie), fSource(fCookie->tty), fTarget(fCookie->other_tty), fRequestOwner(), @@ -645,8 +654,9 @@ // #pragma mark - -ReaderLocker::ReaderLocker(tty_cookie *cookie) - : AbstractLocker(cookie), +ReaderLocker::ReaderLocker(tty_cookie* cookie) + : + AbstractLocker(cookie), fTTY(cookie->tty), fRequestOwner() { @@ -666,7 +676,7 @@ // check the tty queues and notify the next in line, and send out select // events - struct tty *otherTTY = fCookie->other_tty; + struct tty* otherTTY = fCookie->other_tty; tty_notify_if_available(fTTY, (otherTTY->open_count > 0 ? otherTTY : NULL), true); @@ -754,11 +764,11 @@ } -// #pragma mark - +// #pragma mark - int32 -get_tty_index(const char *name) +get_tty_index(const char* name) { // device names follow this form: "pt/%c%x" int8 digit = name[4]; @@ -773,7 +783,7 @@ static void -reset_termios(struct termios &termios) +reset_termios(struct termios& termios) { memset(&termios, 0, sizeof(struct termios)); @@ -800,7 +810,7 @@ void -reset_tty_settings(tty_settings *settings, int32 index) +reset_tty_settings(tty_settings* settings, int32 index) { reset_termios(settings->termios); @@ -817,7 +827,7 @@ void -reset_tty(struct tty *tty, int32 index, mutex* lock, bool isMaster) +reset_tty(struct tty* tty, int32 index, mutex* lock, bool isMaster) { tty->ref_count = 0; tty->open_count = 0; @@ -831,18 +841,18 @@ status_t -tty_output_getc(struct tty *tty, int *_c) +tty_output_getc(struct tty* tty, int* _c) { return B_ERROR; } -/** Processes the input character and puts it into the TTY's input buffer. - * Depending on the termios flags set, signals may be sent, the input - * character changed or removed, etc. - */ +/*! Processes the input character and puts it into the TTY's input buffer. + Depending on the termios flags set, signals may be sent, the input + character changed or removed, etc. +*/ static void -tty_input_putc_locked(struct tty *tty, int c) +tty_input_putc_locked(struct tty* tty, int c) { // process signals if needed @@ -916,7 +926,7 @@ #if 0 status_t -tty_input_putc(struct tty *tty, int c) +tty_input_putc(struct tty* tty, int c) { status_t status = acquire_sem_etc(tty->write_sem, 1, B_CAN_INTERRUPT, 0); if (status != B_OK) @@ -947,7 +957,7 @@ /*! The global lock must be held. */ status_t -init_tty_cookie(tty_cookie *cookie, struct tty *tty, struct tty *otherTTY, +init_tty_cookie(tty_cookie* cookie, struct tty* tty, struct tty* otherTTY, uint32 openMode) { cookie->blocking_semaphore = create_sem(0, "wait for tty close"); @@ -969,7 +979,7 @@ /*! The global lock must be held. */ void -uninit_tty_cookie(tty_cookie *cookie) +uninit_tty_cookie(tty_cookie* cookie) { cookie->tty->ref_count--; @@ -984,11 +994,10 @@ } -/** - * The global lock must be held. - */ +/*! The global lock must be held. +*/ void -add_tty_cookie(tty_cookie *cookie) +add_tty_cookie(tty_cookie* cookie) { MutexLocker locker(cookie->tty->lock); @@ -998,11 +1007,10 @@ } -/** - * The global lock must be held. - */ +/*! The global lock must be held. +*/ void -tty_close_cookie(struct tty_cookie *cookie) +tty_close_cookie(struct tty_cookie* cookie) { MutexLocker locker(gTTYCookieLock); @@ -1119,7 +1127,7 @@ static void -tty_notify_select_event(struct tty *tty, uint8 event) +tty_notify_select_event(struct tty* tty, uint8 event) { TRACE(("tty_notify_select_event(%p, %u)\n", tty, event)); @@ -1128,18 +1136,18 @@ } -/** \brief Checks whether bytes can be read from/written to the line buffer of - * the given TTY and notifies the respective queues. - * - * Also sends out \c B_SELECT_READ and \c B_SELECT_WRITE events as needed. - * - * The TTY and the request lock must be held. - * - * \param tty The TTY. - * \param otherTTY The connected TTY. - */ +/*! \brief Checks whether bytes can be read from/written to the line buffer of + the given TTY and notifies the respective queues. + + Also sends out \c B_SELECT_READ and \c B_SELECT_WRITE events as needed. + + The TTY and the request lock must be held. + + \param tty The TTY. + \param otherTTY The connected TTY. +*/ static void -tty_notify_if_available(struct tty *tty, struct tty *otherTTY, +tty_notify_if_available(struct tty* tty, struct tty* otherTTY, bool notifySelect) { if (!tty) @@ -1169,8 +1177,7 @@ } -/*! - \brief Performs input character conversion and writes the result to +/*! \brief Performs input character conversion and writes the result to \a buffer. \param tty The master tty. \param c The input character. @@ -1216,7 +1223,7 @@ } else if (c == '\n') { if (flags & INLCR) // NL -> CR c = '\r'; - } else if (flags & ISTRIP) // strip of eighth bit + } else if ((flags & ISTRIP) != 0) // strip off eighth bit c &= 0x7f; *buffer = c; @@ -1224,8 +1231,8 @@ return true; } -/*! - \brief Performs output character conversion and writes the result to + +/*! \brief Performs output character conversion and writes the result to \a buffer. \param tty The master tty. \param c The output character. @@ -1237,7 +1244,7 @@ */ static void process_output_char(struct tty* tty, char c, char* buffer, - size_t *_bytesWritten, bool echoed) + size_t* _bytesWritten, bool echoed) { tcflag_t flags = tty->settings->termios.c_oflag; @@ -1293,12 +1300,273 @@ } -// #pragma mark - -// device functions +static status_t +tty_write_to_tty_master_unsafe(tty_cookie* sourceCookie, const char* data, + size_t* _length) +{ + struct tty* source = sourceCookie->tty; + struct tty* target = sourceCookie->other_tty; + size_t length = *_length; + size_t bytesWritten = 0; + uint32 mode = sourceCookie->open_mode; + bool dontBlock = (mode & O_NONBLOCK) != 0; + // bail out, if source is already closed + TTYReference sourceTTYReference(sourceCookie); + if (!sourceTTYReference.IsLocked()) + return B_FILE_ERROR; + if (length == 0) + return B_OK; + + WriterLocker locker(sourceCookie); + + // if the target is not open, fail now + if (target->open_count <= 0) + return B_FILE_ERROR; + + bool echo = (source->settings->termios.c_lflag & ECHO) != 0; + + TRACE(("tty_write_to_tty_master(source = %p, target = %p, " + "length = %lu%s)\n", source, target, length, + (echo ? ", echo mode" : ""))); + + // Make sure we are first in the writer queue(s) and AvailableBytes() is + // initialized. + status_t status = locker.AcquireWriter(dontBlock, 0); + if (status != B_OK) { + *_length = 0; + return status; + } + size_t writable = locker.AvailableBytes(); + size_t writtenSinceLastNotify = 0; + + while (bytesWritten < length) { + // fetch next char and do input processing + char c; + size_t bytesNeeded; + if (!process_input_char(source, *data, &c, &bytesNeeded)) { + // input char shall be skipped + data++; + bytesWritten++; + continue; + } + + // If in echo mode, we do the output conversion and need to update + // the needed bytes count. + char echoBuffer[3]; + size_t echoBytes; + if (echo) { + process_output_char(source, c, echoBuffer, &echoBytes, true); + if (echoBytes > bytesNeeded) + bytesNeeded = echoBytes; + } + + // If there's not enough space to write what we have, we need to wait + // until it is available. + if (writable < bytesNeeded) { + if (writtenSinceLastNotify > 0) { + tty_notify_if_available(target, source, true); + if (echo) + tty_notify_if_available(source, target, true); + writtenSinceLastNotify = 0; + } + + status = locker.AcquireWriter(dontBlock, bytesNeeded); + if (status != B_OK) { + *_length = bytesWritten; + return status; + } + + writable = locker.AvailableBytes(); + + // XXX: do we need to support VMIN & VTIME for write() ? + + // We need to restart the loop, since the termios flags might have + // changed in the meantime (while we've unlocked the tty). Note, + // that we don't re-get "echo" -- maybe we should. + continue; + } + + // write the bytes + tty_input_putc_locked(target, c); + + if (echo) { + for (size_t i = 0; i < echoBytes; i++) + line_buffer_putc(source->input_buffer, echoBuffer[i]); + } + + writable -= bytesNeeded; + data++; + bytesWritten++; + writtenSinceLastNotify++; + } + + return B_OK; +} + + +static status_t +tty_write_to_tty_slave_unsafe(tty_cookie* sourceCookie, const char* data, + size_t* _length) +{ + struct tty* target = sourceCookie->other_tty; + size_t length = *_length; + size_t bytesWritten = 0; + uint32 mode = sourceCookie->open_mode; + bool dontBlock = (mode & O_NONBLOCK) != 0; + + // bail out, if source is already closed + TTYReference sourceTTYReference(sourceCookie); + if (!sourceTTYReference.IsLocked()) + return B_FILE_ERROR; + + if (length == 0) + return B_OK; + + WriterLocker locker(sourceCookie); + + // if the target is not open, fail now + if (target->open_count <= 0) + return B_FILE_ERROR; + + TRACE(("tty_write_to_tty_slave(source = %p, target = %p, length = %lu)\n", + sourceCookie->tty, target, length)); + + // Make sure we are first in the writer queue(s) and AvailableBytes() is + // initialized. + status_t status = locker.AcquireWriter(dontBlock, 0); + if (status != B_OK) { + *_length = 0; + return status; + } + size_t writable = locker.AvailableBytes(); + size_t writtenSinceLastNotify = 0; + + while (bytesWritten < length) { + // fetch next char and do output processing + char buffer[3]; + size_t bytesNeeded; + process_output_char(target, *data, buffer, &bytesNeeded, false); + + // If there's not enough space to write what we have, we need to wait + // until it is available. + if (writable < bytesNeeded) { + if (writtenSinceLastNotify > 0) { + tty_notify_if_available(target, sourceCookie->tty, true); + writtenSinceLastNotify = 0; + } + + status = locker.AcquireWriter(dontBlock, bytesNeeded); + if (status != B_OK) { + *_length = bytesWritten; + return status; + } + + writable = locker.AvailableBytes(); + + // We need to restart the loop, since the termios flags might have + // changed in the meantime (while we've unlocked the tty). + continue; + } + + // write the bytes + for (size_t i = 0; i < bytesNeeded; i++) + line_buffer_putc(target->input_buffer, buffer[i]); + + writable -= bytesNeeded; + data++; + bytesWritten++; + writtenSinceLastNotify++; + } + + return B_OK; +} + + +static void +dump_tty_settings(struct tty_settings& settings) +{ + kprintf(" pgrp_id: %ld\n", settings.pgrp_id); + kprintf(" session_id: %ld\n", settings.session_id); + + kprintf(" termios:\n"); + kprintf(" c_iflag: 0x%08lx\n", settings.termios.c_iflag); + kprintf(" c_oflag: 0x%08lx\n", settings.termios.c_oflag); + kprintf(" c_cflag: 0x%08lx\n", settings.termios.c_cflag); + kprintf(" c_lflag: 0x%08lx\n", settings.termios.c_lflag); + kprintf(" c_line: %d\n", settings.termios.c_line); + kprintf(" c_ispeed: %u\n", settings.termios.c_ispeed); + kprintf(" c_ospeed: %u\n", settings.termios.c_ospeed); + for (int i = 0; i < NCCS; i++) + kprintf(" c_cc[%02d]: %d\n", i, settings.termios.c_cc[i]); + + kprintf(" wsize: %u x %u c, %u x %u pxl\n", + settings.window_size.ws_row, settings.window_size.ws_col, + settings.window_size.ws_xpixel, settings.window_size.ws_ypixel); +} + + +static void +dump_tty_struct(struct tty& tty) +{ + kprintf(" tty @: %p\n", &tty); + kprintf(" index: %ld\n", tty.index); + kprintf(" is_master: %s\n", tty.is_master ? "true" : "false"); + kprintf(" open_count: %ld\n", tty.open_count); + kprintf(" select_pool: %p\n", tty.select_pool); + kprintf(" pending_eof: %lu\n", tty.pending_eof); + kprintf(" lock: %p\n", tty.lock); + + kprintf(" input_buffer:\n"); + kprintf(" first: %ld\n", tty.input_buffer.first); + kprintf(" in: %lu\n", tty.input_buffer.in); + kprintf(" size: %lu\n", tty.input_buffer.size); + kprintf(" buffer: %p\n", tty.input_buffer.buffer); + + kprintf(" reader queue:\n"); + tty.reader_queue.Dump(" "); + kprintf(" writer queue:\n"); + tty.writer_queue.Dump(" "); + + kprintf(" cookies: "); + TTYCookieList::Iterator it = tty.cookies.GetIterator(); + while (tty_cookie* cookie = it.Next()) + kprintf(" %p", cookie); + kprintf("\n"); +} + + +static int +dump_tty(int argc, char** argv) +{ + if (argc < 2) { + kprintf("Usage: %s <tty index>\n", argv[0]); + return 0; + } + + int32 index = atol(argv[1]); + if (index < 0 || index >= (int32)kNumTTYs) { + kprintf("Invalid tty index.\n"); + return 0; + } + + kprintf("master:\n"); + dump_tty_struct(gMasterTTYs[index]); + kprintf("slave:\n"); + dump_tty_struct(gSlaveTTYs[index]); + kprintf("settings:\n"); + dump_tty_settings(gTTYSettings[index]); + + return 0; +} + + +// #pragma mark - device functions + + status_t -tty_close(struct tty *tty) +tty_close(struct tty* tty) { // destroy the queues tty->reader_queue.~RequestQueue(); @@ -1312,7 +1580,7 @@ status_t -tty_open(struct tty *tty, tty_service_func func) +tty_open(struct tty* tty, tty_service_func func) { if (init_line_buffer(tty->input_buffer, TTY_BUFFER_SIZE) < B_OK) return B_NO_MEMORY; @@ -1329,9 +1597,9 @@ status_t -tty_ioctl(tty_cookie *cookie, uint32 op, void *buffer, size_t length) +tty_ioctl(tty_cookie* cookie, uint32 op, void* buffer, size_t length) { - struct tty *tty = cookie->tty; + struct tty* tty = cookie->tty; // bail out, if already closed TTYReference ttyReference(cookie); @@ -1343,7 +1611,7 @@ // values marked BeOS are non-standard codes we support for legacy apps switch (op) { - /* blocking/non-blocking mode */ + // blocking/non-blocking mode case B_SET_BLOCKING_IO: cookie->open_mode &= ~O_NONBLOCK; @@ -1352,7 +1620,7 @@ cookie->open_mode |= O_NONBLOCK; return B_OK; - /* get and set TTY attributes */ + // get and set TTY attributes case TCGETA: TRACE(("tty: get attributes\n")); @@ -1370,7 +1638,7 @@ return user_memcpy(&tty->settings->termios, buffer, sizeof(struct termios)); - /* get and set process group ID */ + // get and set process group ID case TIOCGPGRP: TRACE(("tty: get pgrp_id\n")); @@ -1392,7 +1660,7 @@ return error; } - /* get and set window size */ + // get and set window size case TIOCGWINSZ: TRACE(("tty: set window size\n")); @@ -1446,7 +1714,7 @@ return B_OK; } - case 'ichr': // BeOS (int *) (pre- select() support) + case 'ichr': // BeOS (int*) (pre- select() support) { int wanted; int toRead; @@ -1475,10 +1743,10 @@ return B_OK; } - case TCWAITEVENT: // BeOS (uint *) + case TCWAITEVENT: // BeOS (uint*) // wait for event (timeout if !NULL) - case TCVTIME: // BeOS (bigtime_t *) set highrez VTIME - case 'ochr': // BeOS (int *) same as ichr for write + case TCVTIME: // BeOS (bigtime_t*) set highrez VTIME + case 'ochr': // BeOS (int*) same as ichr for write dprintf("tty: unsupported legacy opcode %lu\n", op); // TODO ? break; @@ -1507,9 +1775,9 @@ status_t -tty_input_read(tty_cookie *cookie, void *buffer, size_t *_length) +tty_input_read(tty_cookie* cookie, void* buffer, size_t* _length) { - struct tty *tty = cookie->tty; + struct tty* tty = cookie->tty; uint32 mode = cookie->open_mode; bool dontBlock = (mode & O_NONBLOCK) != 0; size_t length = *_length; @@ -1582,7 +1850,7 @@ if (canon && tty->pending_eof > 0) hitEOF = &_hitEOF; - bytesRead = line_buffer_user_read(tty->input_buffer, (char *)buffer, + bytesRead = line_buffer_user_read(tty->input_buffer, (char*)buffer, toRead, tty->settings->termios.c_cc[VEOF], hitEOF); if (bytesRead < B_OK) { *_length = 0; @@ -1601,115 +1869,9 @@ } -static status_t -tty_write_to_tty_master_unsafe(tty_cookie *sourceCookie, const char *data, - size_t *_length) -{ - struct tty *source = sourceCookie->tty; - struct tty *target = sourceCookie->other_tty; - size_t length = *_length; - size_t bytesWritten = 0; - uint32 mode = sourceCookie->open_mode; - bool dontBlock = (mode & O_NONBLOCK) != 0; - - // bail out, if source is already closed - TTYReference sourceTTYReference(sourceCookie); - if (!sourceTTYReference.IsLocked()) - return B_FILE_ERROR; - - if (length == 0) - return B_OK; - - WriterLocker locker(sourceCookie); - - // if the target is not open, fail now - if (target->open_count <= 0) - return B_FILE_ERROR; - - bool echo = (source->settings->termios.c_lflag & ECHO) != 0; - - TRACE(("tty_write_to_tty_master(source = %p, target = %p, " - "length = %lu%s)\n", source, target, length, - (echo ? ", echo mode" : ""))); - - // Make sure we are first in the writer queue(s) and AvailableBytes() is - // initialized. - status_t status = locker.AcquireWriter(dontBlock, 0); - if (status != B_OK) { - *_length = 0; - return status; - } - size_t writable = locker.AvailableBytes(); - size_t writtenSinceLastNotify = 0; - - while (bytesWritten < length) { - // fetch next char and do input processing - char c; - size_t bytesNeeded; - if (!process_input_char(source, *data, &c, &bytesNeeded)) { - // input char shall be skipped - data++; - bytesWritten++; - continue; - } - - // If in echo mode, we do the output conversion and need to update - // the needed bytes count. - char echoBuffer[3]; - size_t echoBytes; - if (echo) { - process_output_char(source, c, echoBuffer, &echoBytes, true); - if (echoBytes > bytesNeeded) - bytesNeeded = echoBytes; - } - - // If there's not enough space to write what we have, we need to wait - // until it is available. - if (writable < bytesNeeded) { - if (writtenSinceLastNotify > 0) { - tty_notify_if_available(target, source, true); - if (echo) - tty_notify_if_available(source, target, true); - writtenSinceLastNotify = 0; - } - - status = locker.AcquireWriter(dontBlock, bytesNeeded); - if (status != B_OK) { - *_length = bytesWritten; - return status; - } [... truncated: 245 lines follow ...]