/* * Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ #ifndef TTY_PRIVATE_H #define TTY_PRIVATE_H #include #include #include #include #include #include #include #include #include "line_buffer.h" #define TTY_BUFFER_SIZE 4096 // The only nice Rico'ism :) #define CTRL(c) ((c) - 0100) class RequestOwner; class Semaphore; struct tty; struct tty_cookie; class Request : public DoublyLinkedListLinkImpl { 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 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 { struct tty *tty; struct tty *other_tty; uint32 open_mode; int32 thread_count; sem_id blocking_semaphore; bool closed; }; typedef DoublyLinkedList 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; recursive_lock* lock; tty_settings* settings; uint8 hardware_bits; bool is_exclusive; }; extern struct mutex gTTYCookieLock; extern struct recursive_lock gTTYRequestLock; extern status_t tty_create(tty_service_func func, struct tty *masterTTY, struct tty **tty); extern void tty_destroy(struct tty *tty); extern status_t tty_create_cookie(struct tty *tty, struct tty *otherTTY, uint32 openMode, struct tty_cookie **cookie); extern void tty_destroy_cookie(tty_cookie *cookie); extern void tty_close_cookie(tty_cookie *cookie); extern status_t tty_read(tty_cookie *cookie, void *buffer, size_t *_length); extern status_t tty_write(tty_cookie *sourceCookie, const void *buffer, size_t *_length); extern status_t tty_control(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); extern status_t tty_input_lock(tty_cookie* cookie, bool lock); extern status_t tty_hardware_signal(tty_cookie* cookie, int signal, bool); #endif /* TTY_PRIVATE_H */