Author: mmlr Date: 2011-06-10 19:35:46 +0200 (Fri, 10 Jun 2011) New Revision: 42089 Changeset: https://dev.haiku-os.org/changeset/42089 Modified: haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/ACM.cpp haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/ACM.h haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.h Log: * Finish the port to the new tty module. Back when I left off last time it was only halfway finished. The way it is supposed to work is that there are two tty cookies, representing the system and the device side. Reads and writes coming from the system and going to the device are using the system cookie while reads and writes coming from the device use the device cookie. * Move writing to the device into an output thread, similar to how reading from the device works. This isn't necessarily a good idea and might be moved back into the write hook again to ensure that writes can be made blocking. Right now if you just write and then close, the writes will most likely be canceled before every going out to the device. * Removed the read and write lock mutex. They aren't necessary as the tty layer will serialize the reads and writes anyway. * Made simply copying the data to the write buffer the default implementation of the OnWrite callback and removed the OnWrite in ACMDevice. The ProlificDevice didn't provide an OnWrite hook before, so it would've never written anything. * Break out the baud index to speed mapping into an inline function. Since the defines might change in termios.h just adding an array is a bit fragile (it already missed one entry and would've been broken for certain speeds). This should make usb_serial usable for some (most?) cases. I've tested this with an Arduino board that uses an FTDI interface. As mentioned above, since writes currently just write into the tty layer and don't wait for the data to be flushed, and since close doesn't wait for the output buffers to be drained either, a simple write and close (as in "echo a > /dev/ports/usb0") will in most cases cancel the output before it is written to the device. I'm looking into a few ways to fix that next. Modified: haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/ACM.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/ACM.cpp 2011-06-10 17:20:27 UTC (rev 42088) +++ haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/ACM.cpp 2011-06-10 17:35:46 UTC (rev 42089) @@ -134,10 +134,3 @@ TRACE_FUNCRET("< ACMDevice::SetControlLineState() returns: 0x%08x\n", status); return status; } - - -void -ACMDevice::OnWrite(const char *buffer, size_t *numBytes, size_t *packetBytes) -{ - memcpy(WriteBuffer(), buffer, *numBytes); -} Modified: haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/ACM.h =================================================================== --- haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/ACM.h 2011-06-10 17:20:27 UTC (rev 42088) +++ haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/ACM.h 2011-06-10 17:35:46 UTC (rev 42089) @@ -19,9 +19,6 @@ virtual status_t SetLineCoding(usb_cdc_line_coding *coding); virtual status_t SetControlLineState(uint16 state); - -virtual void OnWrite(const char *buffer, size_t *numBytes, - size_t *packetBytes); }; #endif //_USB_ACM_H_ Modified: haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp 2011-06-10 17:20:27 UTC (rev 42088) +++ haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp 2011-06-10 17:35:46 UTC (rev 42089) @@ -29,6 +29,8 @@ fBufferArea(-1), fReadBuffer(NULL), fReadBufferSize(ROUNDUP(DEF_BUFFER_SIZE, 16)), + fOutputBuffer(NULL), + fOutputBufferSize(ROUNDUP(DEF_BUFFER_SIZE, 16)), fWriteBuffer(NULL), fWriteBufferSize(ROUNDUP(DEF_BUFFER_SIZE, 16)), fInterruptBuffer(NULL), @@ -39,12 +41,12 @@ fInputStopped(false), fMasterTTY(NULL), fSlaveTTY(NULL), - fTTYCookie(NULL), - fDeviceThread(-1), - fStopDeviceThread(false) + fSystemTTYCookie(NULL), + fDeviceTTYCookie(NULL), + fInputThread(-1), + fOutputThread(-1), + fStopThreads(false) { - mutex_init(&fReadLock, "usb_serial read lock"); - mutex_init(&fWriteLock, "usb_serial write lock"); } @@ -59,9 +61,6 @@ if (fBufferArea >= B_OK) delete_area(fBufferArea); - - mutex_destroy(&fReadLock); - mutex_destroy(&fWriteLock); } @@ -70,16 +69,15 @@ { fDoneRead = create_sem(0, "usb_serial:done_read"); fDoneWrite = create_sem(0, "usb_serial:done_write"); - mutex_init(&fReadLock, "usb_serial:read_lock"); - mutex_init(&fWriteLock, "usb_serial:write_lock"); - size_t totalBuffers = fReadBufferSize + fWriteBufferSize + size_t totalBuffers = fReadBufferSize + fOutputBufferSize + fWriteBufferSize + fInterruptBufferSize; fBufferArea = create_area("usb_serial:buffers_area", (void **)&fReadBuffer, B_ANY_KERNEL_ADDRESS, ROUNDUP(totalBuffers, B_PAGE_SIZE), B_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA); - fWriteBuffer = fReadBuffer + fReadBufferSize; + fOutputBuffer = fReadBuffer + fReadBufferSize; + fWriteBuffer = fOutputBuffer + fOutputBufferSize; fInterruptBuffer = fWriteBuffer + fWriteBufferSize; return B_OK; } @@ -106,47 +104,53 @@ } +inline int32 +baud_index_to_speed(int index) +{ + switch (index) { + case B0: return 0; + case B50: return 50; + case B75: return 75; + case B110: return 110; + case B134: return 134; + case B150: return 150; + case B200: return 200; + case B300: return 300; + case B600: return 600; + case B1200: return 1200; + case B1800: return 1800; + case B2400: return 2400; + case B4800: return 4800; + case B9600: return 9600; + case B19200: return 19200; + case B31250: return 31250; + case B38400: return 38400; + case B57600: return 57600; + case B115200: return 115200; + case B230400: return 230400; + } + + TRACE_ALWAYS("invalid baud index %d\n", index); + return -1; +} + + void SerialDevice::SetModes(struct termios *tios) { uint16 newControl = fControlOut; TRACE_FUNCRES(trace_termios, tios); - static uint32 baudRates[] = { - 0x00000000, //B0 - 0x00000032, //B50 - 0x0000004B, //B75 - 0x0000006E, //B110 - 0x00000086, //B134 - 0x00000096, //B150 - 0x000000C8, //B200 - 0x0000012C, //B300 - 0x00000258, //B600 - 0x000004B0, //B1200 - 0x00000708, //B1800 - 0x00000960, //B2400 - 0x000012C0, //B4800 - 0x00002580, //B9600 - 0x00004B00, //B19200 - 0x00009600, //B38400 - 0x0000E100, //B57600 - 0x0001C200, //B115200 - 0x00038400, //B230400 - 0x00070800, //460800 - 0x000E1000, //921600 - }; + int32 speed = baud_index_to_speed(tios->c_cflag & CBAUD); + if (speed < 0) + speed = baud_index_to_speed(tios->c_ispeed); + if (speed < 0) + speed = baud_index_to_speed(tios->c_ospeed); + if (speed < 0) + speed = 19200; - uint32 baudCount = sizeof(baudRates) / sizeof(baudRates[0]); - uint32 baudIndex = tios->c_cflag & CBAUD; - if (baudIndex == 0) - baudIndex = tios->c_ispeed; - if (baudIndex == 0) - baudIndex = tios->c_ospeed; - if (baudIndex > baudCount) - baudIndex = baudCount - 1; - usb_cdc_line_coding lineCoding; - lineCoding.speed = baudRates[baudIndex]; + lineCoding.speed = speed; lineCoding.stopbits = (tios->c_cflag & CSTOPB) ? USB_CDC_LINE_CODING_2_STOPBITS : USB_CDC_LINE_CODING_1_STOPBIT; @@ -190,8 +194,8 @@ bool enable = *(bool *)buffer; TRACE("TTYENABLE: %sable\n", enable ? "en" : "dis"); - gTTYModule->tty_hardware_signal(fTTYCookie, TTYHWDCD, enable); - gTTYModule->tty_hardware_signal(fTTYCookie, TTYHWCTS, enable); + gTTYModule->tty_hardware_signal(fSystemTTYCookie, TTYHWDCD, enable); + gTTYModule->tty_hardware_signal(fSystemTTYCookie, TTYHWCTS, enable); fControlOut = enable ? USB_CDC_CONTROL_SIGNAL_STATE_DTR | USB_CDC_CONTROL_SIGNAL_STATE_RTS : 0; @@ -202,19 +206,19 @@ case TTYISTOP: fInputStopped = *(bool *)buffer; TRACE("TTYISTOP: %sstopped\n", fInputStopped ? "" : "not "); - gTTYModule->tty_hardware_signal(fTTYCookie, TTYHWCTS, + gTTYModule->tty_hardware_signal(fSystemTTYCookie, TTYHWCTS, !fInputStopped); return true; case TTYGETSIGNALS: TRACE("TTYGETSIGNALS\n"); - gTTYModule->tty_hardware_signal(fTTYCookie, TTYHWDCD, + gTTYModule->tty_hardware_signal(fSystemTTYCookie, TTYHWDCD, (fControlOut & (USB_CDC_CONTROL_SIGNAL_STATE_DTR | USB_CDC_CONTROL_SIGNAL_STATE_RTS)) != 0); - gTTYModule->tty_hardware_signal(fTTYCookie, TTYHWCTS, + gTTYModule->tty_hardware_signal(fSystemTTYCookie, TTYHWCTS, !fInputStopped); - gTTYModule->tty_hardware_signal(fTTYCookie, TTYHWDSR, false); - gTTYModule->tty_hardware_signal(fTTYCookie, TTYHWRI, false); + gTTYModule->tty_hardware_signal(fSystemTTYCookie, TTYHWDSR, false); + gTTYModule->tty_hardware_signal(fSystemTTYCookie, TTYHWRI, false); return true; case TTYSETMODES: @@ -263,39 +267,60 @@ return B_NO_MEMORY; } - fSlaveTTY = gTTYModule->tty_create(NULL, false); + fSlaveTTY = gTTYModule->tty_create(usb_serial_service, false); if (fSlaveTTY == NULL) { TRACE_ALWAYS("open: failed to init slave tty\n"); gTTYModule->tty_destroy(fMasterTTY); return B_NO_MEMORY; } - fTTYCookie = gTTYModule->tty_create_cookie(fMasterTTY, fSlaveTTY, flags); - if (fTTYCookie == NULL) { - TRACE_ALWAYS("open: failed to init tty cookie\n"); + fSystemTTYCookie = gTTYModule->tty_create_cookie(fMasterTTY, fSlaveTTY, + flags); + if (fSystemTTYCookie == NULL) { + TRACE_ALWAYS("open: failed to init system tty cookie\n"); gTTYModule->tty_destroy(fMasterTTY); gTTYModule->tty_destroy(fSlaveTTY); return B_NO_MEMORY; } + fDeviceTTYCookie = gTTYModule->tty_create_cookie(fSlaveTTY, fMasterTTY, + flags); + if (fDeviceTTYCookie == NULL) { + TRACE_ALWAYS("open: failed to init device tty cookie\n"); + gTTYModule->tty_destroy_cookie(fSystemTTYCookie); + gTTYModule->tty_destroy(fMasterTTY); + gTTYModule->tty_destroy(fSlaveTTY); + return B_NO_MEMORY; + } + ResetDevice(); - fDeviceThread = spawn_kernel_thread(DeviceThread, - "usb_serial device thread", B_NORMAL_PRIORITY, this); + fStopThreads = false; - if (fDeviceThread < B_OK) { - TRACE_ALWAYS("open: failed to spawn kernel thread\n"); - return fDeviceThread; + fInputThread = spawn_kernel_thread(_InputThread, + "usb_serial input thread", B_NORMAL_PRIORITY, this); + if (fInputThread < 0) { + TRACE_ALWAYS("open: failed to spawn input thread\n"); + return fInputThread; } - resume_thread(fDeviceThread); + resume_thread(fInputThread); + fOutputThread = spawn_kernel_thread(_OutputThread, + "usb_serial output thread", B_NORMAL_PRIORITY, this); + if (fOutputThread < 0) { + TRACE_ALWAYS("open: failed to spawn output thread\n"); + return fOutputThread; + } + + resume_thread(fOutputThread); + fControlOut = USB_CDC_CONTROL_SIGNAL_STATE_DTR | USB_CDC_CONTROL_SIGNAL_STATE_RTS; SetControlLineState(fControlOut); status_t status = gUSBModule->queue_interrupt(fControlPipe, - fInterruptBuffer, fInterruptBufferSize, InterruptCallbackFunction, + fInterruptBuffer, fInterruptBufferSize, _InterruptCallbackFunction, this); if (status < B_OK) TRACE_ALWAYS("failed to queue initial interrupt\n"); @@ -313,75 +338,19 @@ return B_DEV_NOT_READY; } - status_t status = mutex_lock(&fReadLock); - if (status != B_OK) { - TRACE_ALWAYS("read: failed to get read lock\n"); - *numBytes = 0; - return status; - } - - status = gTTYModule->tty_read(fTTYCookie, buffer, numBytes); - - mutex_unlock(&fReadLock); - return status; + return gTTYModule->tty_read(fSystemTTYCookie, buffer, numBytes); } status_t SerialDevice::Write(const char *buffer, size_t *numBytes) { - size_t bytesLeft = *numBytes; - *numBytes = 0; - - status_t status = mutex_lock(&fWriteLock); - if (status != B_OK) { - TRACE_ALWAYS("write: failed to get write lock\n"); - return status; - } - if (fDeviceRemoved) { - mutex_unlock(&fWriteLock); + *numBytes = 0; return B_DEV_NOT_READY; } - while (bytesLeft > 0) { - size_t length = MIN(bytesLeft, fWriteBufferSize); - size_t packetLength = length; - OnWrite(buffer, &length, &packetLength); - - status = gUSBModule->queue_bulk(fWritePipe, fWriteBuffer, - packetLength, WriteCallbackFunction, this); - if (status < B_OK) { - TRACE_ALWAYS("write: queueing failed with status 0x%08x\n", status); - break; - } - - status = acquire_sem_etc(fDoneWrite, 1, B_CAN_INTERRUPT, 0); - if (status < B_OK) { - TRACE_ALWAYS("write: failed to get write done sem 0x%08x\n", - status); - break; - } - - if (fStatusWrite != B_OK) { - TRACE("write: device status error 0x%08x\n", fStatusWrite); - status = gUSBModule->clear_feature(fWritePipe, - USB_FEATURE_ENDPOINT_HALT); - if (status < B_OK) { - TRACE_ALWAYS("write: failed to clear device halt\n"); - status = B_ERROR; - break; - } - continue; - } - - buffer += length; - *numBytes += length; - bytesLeft -= length; - } - - mutex_unlock(&fWriteLock); - return status; + return gTTYModule->tty_write(fSystemTTYCookie, buffer, numBytes); } @@ -391,7 +360,9 @@ if (fDeviceRemoved) return B_DEV_NOT_READY; - return gTTYModule->tty_control(fTTYCookie, op, arg, length); + gTTYModule->tty_control(fSystemTTYCookie, op, arg, length); + gTTYModule->tty_control(fDeviceTTYCookie, op, arg, length); + return B_OK; } @@ -401,7 +372,7 @@ if (fDeviceRemoved) return B_DEV_NOT_READY; - return gTTYModule->tty_select(fTTYCookie, event, ref, sync); + return gTTYModule->tty_select(fSystemTTYCookie, event, ref, sync); } @@ -411,7 +382,7 @@ if (fDeviceRemoved) return B_DEV_NOT_READY; - return gTTYModule->tty_deselect(fTTYCookie, event, sync); + return gTTYModule->tty_deselect(fSystemTTYCookie, event, sync); } @@ -420,14 +391,30 @@ { OnClose(); + // TODO: wait for the output buffer to be flushed? + + fStopThreads = true; + fInputStopped = false; + if (!fDeviceRemoved) { gUSBModule->cancel_queued_transfers(fReadPipe); gUSBModule->cancel_queued_transfers(fWritePipe); gUSBModule->cancel_queued_transfers(fControlPipe); } - gTTYModule->tty_destroy_cookie(fTTYCookie); + int32 result = B_OK; + wait_for_thread(fInputThread, &result); + fInputThread = -1; + wait_for_thread(fOutputThread, &result); + fOutputThread = -1; + + gTTYModule->tty_destroy_cookie(fSystemTTYCookie); + gTTYModule->tty_destroy_cookie(fDeviceTTYCookie); + + gTTYModule->tty_destroy(fMasterTTY); + gTTYModule->tty_destroy(fSlaveTTY); + fDeviceOpen = false; return B_OK; } @@ -436,8 +423,6 @@ status_t SerialDevice::Free() { - gTTYModule->tty_destroy(fMasterTTY); - gTTYModule->tty_destroy(fSlaveTTY); return B_OK; } @@ -452,18 +437,18 @@ fDeviceRemoved = true; // we need to ensure that we do not use the device anymore - fStopDeviceThread = true; + fStopThreads = true; fInputStopped = false; gUSBModule->cancel_queued_transfers(fReadPipe); gUSBModule->cancel_queued_transfers(fWritePipe); gUSBModule->cancel_queued_transfers(fControlPipe); int32 result = B_OK; - wait_for_thread(fDeviceThread, &result); - fDeviceThread = -1; + wait_for_thread(fInputThread, &result); + fInputThread = -1; - mutex_lock(&fWriteLock); - mutex_unlock(&fWriteLock); + wait_for_thread(fOutputThread, &result); + fOutputThread = -1; } @@ -509,7 +494,7 @@ void SerialDevice::OnWrite(const char *buffer, size_t *numBytes, size_t *packetBytes) { - // default implementation - does nothing + memcpy(fWriteBuffer, buffer, *numBytes); } @@ -521,35 +506,37 @@ int32 -SerialDevice::DeviceThread(void *data) +SerialDevice::_InputThread(void *data) { SerialDevice *device = (SerialDevice *)data; - while (!device->fStopDeviceThread) { + while (!device->fStopThreads) { status_t status = gUSBModule->queue_bulk(device->fReadPipe, device->fReadBuffer, device->fReadBufferSize, - device->ReadCallbackFunction, data); + device->_ReadCallbackFunction, data); if (status < B_OK) { - TRACE_ALWAYS("device thread: queueing failed with error: 0x%08x\n", + TRACE_ALWAYS("input thread: queueing failed with error: 0x%08x\n", status); - break; + return status; } status = acquire_sem_etc(device->fDoneRead, 1, B_CAN_INTERRUPT, 0); if (status < B_OK) { - TRACE_ALWAYS("device thread: failed to get read done sem 0x%08x\n", + TRACE_ALWAYS("input thread: failed to get read done sem 0x%08x\n", status); - break; + return status; } if (device->fStatusRead != B_OK) { - TRACE("device thread: device status error 0x%08x\n", + TRACE("input thread: device status error 0x%08x\n", device->fStatusRead); if (gUSBModule->clear_feature(device->fReadPipe, USB_FEATURE_ENDPOINT_HALT) != B_OK) { - TRACE_ALWAYS("device thread: failed to clear halt feature\n"); - break; + TRACE_ALWAYS("input thread: failed to clear halt feature\n"); + return B_ERROR; } + + continue; } char *buffer = device->fReadBuffer; @@ -561,15 +548,79 @@ while (device->fInputStopped) snooze(100); - gTTYModule->tty_write(device->fTTYCookie, buffer, &readLength); + status = gTTYModule->tty_write(device->fDeviceTTYCookie, buffer, + &readLength); + if (status != B_OK) { + TRACE_ALWAYS("input thread: failed to write into TTY\n"); + return status; + } } return B_OK; } +int32 +SerialDevice::_OutputThread(void *data) +{ + SerialDevice *device = (SerialDevice *)data; + + while (!device->fStopThreads) { + char *buffer = device->fOutputBuffer; + size_t bytesLeft = device->fOutputBufferSize; + status_t status = gTTYModule->tty_read(device->fDeviceTTYCookie, buffer, + &bytesLeft); + if (status != B_OK) { + TRACE_ALWAYS("output thread: failed to read from TTY\n"); + return status; + } + + while (bytesLeft > 0) { + size_t length = MIN(bytesLeft, device->fWriteBufferSize); + size_t packetLength = length; + device->OnWrite(buffer, &length, &packetLength); + + status = gUSBModule->queue_bulk(device->fWritePipe, + device->fWriteBuffer, packetLength, _WriteCallbackFunction, + device); + if (status < B_OK) { + TRACE_ALWAYS("output thread: queueing failed with status " + "0x%08x\n", status); + return status; + } + + status = acquire_sem_etc(device->fDoneWrite, 1, B_CAN_INTERRUPT, 0); + if (status != B_OK) { + TRACE_ALWAYS("output thread: failed to get write done sem " + "0x%08x\n", status); + return status; + } + + if (device->fStatusWrite != B_OK) { + TRACE("output thread: device status error 0x%08x\n", + device->fStatusWrite); + status = gUSBModule->clear_feature(device->fWritePipe, + USB_FEATURE_ENDPOINT_HALT); + if (status < B_OK) { + TRACE_ALWAYS("output thread: failed to clear device " + "halt\n"); + return B_ERROR; + } + + continue; + } + + buffer += length; + bytesLeft -= length; + } + } + + return B_OK; +} + + void -SerialDevice::ReadCallbackFunction(void *cookie, int32 status, void *data, +SerialDevice::_ReadCallbackFunction(void *cookie, int32 status, void *data, uint32 actualLength) { TRACE_FUNCALLS("read callback: cookie: 0x%08x status: 0x%08x data: 0x%08x " @@ -583,7 +634,7 @@ void -SerialDevice::WriteCallbackFunction(void *cookie, int32 status, void *data, +SerialDevice::_WriteCallbackFunction(void *cookie, int32 status, void *data, uint32 actualLength) { TRACE_FUNCALLS("write callback: cookie: 0x%08x status: 0x%08x data: 0x%08x " @@ -597,7 +648,7 @@ void -SerialDevice::InterruptCallbackFunction(void *cookie, int32 status, +SerialDevice::_InterruptCallbackFunction(void *cookie, int32 status, void *data, uint32 actualLength) { TRACE_FUNCALLS("interrupt callback: cookie: 0x%08x status: 0x%08x data: " @@ -612,7 +663,7 @@ if (status == B_OK && !device->fDeviceRemoved) { status = gUSBModule->queue_interrupt(device->fControlPipe, device->fInterruptBuffer, device->fInterruptBufferSize, - device->InterruptCallbackFunction, device); + device->_InterruptCallbackFunction, device); } } Modified: haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.h =================================================================== --- haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.h 2011-06-10 17:20:27 UTC (rev 42088) +++ haiku/trunk/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.h 2011-06-10 17:35:46 UTC (rev 42089) @@ -76,16 +76,18 @@ void SetReadBufferSize(size_t size) { fReadBufferSize = size; }; void SetWriteBufferSize(size_t size) { fWriteBufferSize = size; }; void SetInterruptBufferSize(size_t size) { fInterruptBufferSize = size; }; + private: -static int32 DeviceThread(void *data); +static int32 _InputThread(void *data); +static int32 _OutputThread(void *data); -static void ReadCallbackFunction(void *cookie, +static void _ReadCallbackFunction(void *cookie, int32 status, void *data, uint32 actualLength); -static void WriteCallbackFunction(void *cookie, +static void _WriteCallbackFunction(void *cookie, int32 status, void *data, uint32 actualLength); -static void InterruptCallbackFunction(void *cookie, +static void _InterruptCallbackFunction(void *cookie, int32 status, void *data, uint32 actualLength); @@ -108,6 +110,8 @@ area_id fBufferArea; char * fReadBuffer; size_t fReadBufferSize; + char * fOutputBuffer; + size_t fOutputBufferSize; char * fWriteBuffer; size_t fWriteBufferSize; char * fInterruptBuffer; @@ -129,15 +133,13 @@ bool fInputStopped; struct tty * fMasterTTY; struct tty * fSlaveTTY; - struct tty_cookie * fTTYCookie; + struct tty_cookie * fSystemTTYCookie; + struct tty_cookie * fDeviceTTYCookie; - /* device thread management */ - thread_id fDeviceThread; - bool fStopDeviceThread; - - /* device locks to ensure no concurent reads/writes */ - mutex fReadLock; - mutex fWriteLock; + /* input/output thread management */ + thread_id fInputThread; + thread_id fOutputThread; + bool fStopThreads; }; #endif // _USB_DEVICE_H_