[haiku-commits] r34142 - haiku/trunk/src/add-ons/kernel/drivers/tty

  • From: axeld@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 19 Nov 2009 23:00:24 +0100 (CET)

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 ...]

Other related posts:

  • » [haiku-commits] r34142 - haiku/trunk/src/add-ons/kernel/drivers/tty - axeld