diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/BeOSCompatibility.h b/src/add-ons/kernel/drivers/ports/pc_serial/BeOSCompatibility.h new file mode 100644 index 0000000000..62760f31ac --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/pc_serial/BeOSCompatibility.h @@ -0,0 +1,54 @@ +#ifndef _BEOS_COMPATIBILITY_H_ +#define _BEOS_COMPATIBILITY_H_ +#ifndef HAIKU_TARGET_PLATFORM_HAIKU + +typedef struct mutex { + sem_id sem; + int32 count; +} mutex; + + +static inline status_t +mutex_init(mutex *ben, const char *name) +{ + if (ben == NULL || name == NULL) + return B_BAD_VALUE; + + ben->count = 1; + ben->sem = create_sem(0, name); + if (ben->sem >= B_OK) + return B_OK; + + return ben->sem; +} + + +static inline void +mutex_destroy(mutex *ben) +{ + delete_sem(ben->sem); + ben->sem = -1; +} + + +static inline status_t +mutex_lock(mutex *ben) +{ + if (atomic_add(&ben->count, -1) <= 0) + return acquire_sem(ben->sem); + + return B_OK; +} + + +static inline status_t +mutex_unlock(mutex *ben) +{ + if (atomic_add(&ben->count, 1) < 0) + return release_sem(ben->sem); + + return B_OK; +} + +#endif // HAIKU_TARGET_PLATFORM_HAIKU +#endif // _BEOS_COMPATIBILITY_H_ diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/Driver.cpp b/src/add-ons/kernel/drivers/ports/pc_serial/Driver.cpp new file mode 100644 index 0000000000..51304fa250 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/pc_serial/Driver.cpp @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2007-2008 by Michael Lotz + * Heavily based on the original usb_serial driver which is: + * + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + */ +#include +#include +#include +#include +#include + +#include "Driver.h" +#include "SerialDevice.h" + +static const char *sDeviceBaseName = "ports/serial"; +SerialDevice *gSerialDevices[DEVICES_COUNT]; +char *gDeviceNames[DEVICES_COUNT + 1]; +usb_module_info *gUSBModule = NULL; +tty_module_info *gTTYModule = NULL; +struct ddomain gSerialDomain; +sem_id gDriverLock = -1; + + +status_t +pc_serial_device_added(pc_device device, void **cookie) +{ + TRACE_FUNCALLS("> pc_serial_device_added(0x%08x, 0x%08x)\n", device, cookie); + + status_t status = B_OK; + const pc_device_descriptor *descriptor + = gUSBModule->get_device_descriptor(device); + + TRACE_ALWAYS("probing device: 0x%04x/0x%04x\n", descriptor->vendor_id, + descriptor->product_id); + + *cookie = NULL; + SerialDevice *serialDevice = SerialDevice::MakeDevice(device, + descriptor->vendor_id, descriptor->product_id); + + const pc_configuration_info *configuration + = gUSBModule->get_nth_configuration(device, 0); + + if (!configuration) + return B_ERROR; + + status = serialDevice->AddDevice(configuration); + if (status < B_OK) { + delete serialDevice; + return status; + } + + acquire_sem(gDriverLock); + for (int32 i = 0; i < DEVICES_COUNT; i++) { + if (gSerialDevices[i] != NULL) + continue; + + status = serialDevice->Init(); + if (status < B_OK) { + delete serialDevice; + return status; + } + + gSerialDevices[i] = serialDevice; + *cookie = serialDevice; + + release_sem(gDriverLock); + TRACE_ALWAYS("%s (0x%04x/0x%04x) added\n", serialDevice->Description(), + descriptor->vendor_id, descriptor->product_id); + return B_OK; + } + + release_sem(gDriverLock); + return B_ERROR; +} + + +status_t +pc_serial_device_removed(void *cookie) +{ + TRACE_FUNCALLS("> pc_serial_device_removed(0x%08x)\n", cookie); + + acquire_sem(gDriverLock); + + SerialDevice *device = (SerialDevice *)cookie; + for (int32 i = 0; i < DEVICES_COUNT; i++) { + if (gSerialDevices[i] == device) { + if (device->IsOpen()) { + // the device will be deleted upon being freed + device->Removed(); + } else { + delete device; + gSerialDevices[i] = NULL; + } + break; + } + } + + release_sem(gDriverLock); + TRACE_FUNCRET("< pc_serial_device_removed() returns\n"); + return B_OK; +} + + +//#pragma mark - + + +/* init_hardware - called once the first time the driver is loaded */ +status_t +init_hardware() +{ + TRACE("init_hardware\n"); + return B_OK; +} + + +/* init_driver - called every time the driver is loaded. */ +status_t +init_driver() +{ + load_settings(); + create_log_file(); + + TRACE_FUNCALLS("> init_driver()\n"); + + status_t status = get_module(B_TTY_MODULE_NAME, (module_info **)&gTTYModule); + if (status < B_OK) + return status; + + status = get_module(B_USB_MODULE_NAME, (module_info **)&gUSBModule); + if (status < B_OK) { + put_module(B_TTY_MODULE_NAME); + return status; + } + + for (int32 i = 0; i < DEVICES_COUNT; i++) + gSerialDevices[i] = NULL; + + gDeviceNames[0] = NULL; + + gDriverLock = create_sem(1, DRIVER_NAME"_devices_table_lock"); + if (gDriverLock < B_OK) { + put_module(B_USB_MODULE_NAME); + put_module(B_TTY_MODULE_NAME); + return gDriverLock; + } + + static pc_notify_hooks notifyHooks = { + &pc_serial_device_added, + &pc_serial_device_removed + }; + + gUSBModule->register_driver(DRIVER_NAME, NULL, 0, NULL); + gUSBModule->install_notify(DRIVER_NAME, ¬ifyHooks); + TRACE_FUNCRET("< init_driver() returns\n"); + return B_OK; +} + + +/* uninit_driver - called every time the driver is unloaded */ +void +uninit_driver() +{ + TRACE_FUNCALLS("> uninit_driver()\n"); + + gUSBModule->uninstall_notify(DRIVER_NAME); + acquire_sem(gDriverLock); + + for (int32 i = 0; i < DEVICES_COUNT; i++) { + if (gSerialDevices[i]) { + delete gSerialDevices[i]; + gSerialDevices[i] = NULL; + } + } + + for (int32 i = 0; gDeviceNames[i]; i++) + free(gDeviceNames[i]); + + delete_sem(gDriverLock); + put_module(B_USB_MODULE_NAME); + put_module(B_TTY_MODULE_NAME); + + TRACE_FUNCRET("< uninit_driver() returns\n"); +} + + +bool +pc_serial_service(struct tty *ptty, struct ddrover *ddr, uint flags) +{ + TRACE_FUNCALLS("> pc_serial_service(0x%08x, 0x%08x, 0x%08x)\n", ptty, ddr, flags); + + for (int32 i = 0; i < DEVICES_COUNT; i++) { + if (gSerialDevices[i] && gSerialDevices[i]->Service(ptty, ddr, flags)) { + TRACE_FUNCRET("< pc_serial_service() returns: true\n"); + return true; + } + } + + TRACE_FUNCRET("< pc_serial_service() returns: false\n"); + return false; +} + + +/* pc_serial_open - handle open() calls */ +static status_t +pc_serial_open(const char *name, uint32 flags, void **cookie) +{ + TRACE_FUNCALLS("> pc_serial_open(%s, 0x%08x, 0x%08x)\n", name, flags, cookie); + acquire_sem(gDriverLock); + status_t status = ENODEV; + + *cookie = NULL; + int i = strtol(name + strlen(sDeviceBaseName), NULL, 10); + if (i >= 0 && i < DEVICES_COUNT && gSerialDevices[i]) { + status = gSerialDevices[i]->Open(flags); + *cookie = gSerialDevices[i]; + } + + release_sem(gDriverLock); + TRACE_FUNCRET("< pc_serial_open() returns: 0x%08x\n", status); + return status; +} + + +/* pc_serial_read - handle read() calls */ +static status_t +pc_serial_read(void *cookie, off_t position, void *buffer, size_t *numBytes) +{ + TRACE_FUNCALLS("> pc_serial_read(0x%08x, %Ld, 0x%08x, %d)\n", cookie, + position, buffer, *numBytes); + SerialDevice *device = (SerialDevice *)cookie; + return device->Read((char *)buffer, numBytes); +} + + +/* pc_serial_write - handle write() calls */ +static status_t +pc_serial_write(void *cookie, off_t position, const void *buffer, + size_t *numBytes) +{ + TRACE_FUNCALLS("> pc_serial_write(0x%08x, %Ld, 0x%08x, %d)\n", cookie, + position, buffer, *numBytes); + SerialDevice *device = (SerialDevice *)cookie; + return device->Write((const char *)buffer, numBytes); +} + + +/* pc_serial_control - handle ioctl calls */ +static status_t +pc_serial_control(void *cookie, uint32 op, void *arg, size_t length) +{ + TRACE_FUNCALLS("> pc_serial_control(0x%08x, 0x%08x, 0x%08x, %d)\n", + cookie, op, arg, length); + SerialDevice *device = (SerialDevice *)cookie; + return device->Control(op, arg, length); +} + + +#if defined(B_BEOS_VERSION_DANO) || defined(__HAIKU__) +/* pc_serial_select - handle select start */ +static status_t +pc_serial_select(void *cookie, uint8 event, uint32 ref, selectsync *sync) +{ + TRACE_FUNCALLS("> pc_serial_select(0x%08x, 0x%08x, 0x%08x, %p)\n", + cookie, event, ref, sync); + SerialDevice *device = (SerialDevice *)cookie; + return device->Select(event, ref, sync); +} + + +/* pc_serial_deselect - handle select exit */ +static status_t +pc_serial_deselect(void *cookie, uint8 event, selectsync *sync) +{ + TRACE_FUNCALLS("> pc_serial_deselect(0x%08x, 0x%08x, %p)\n", + cookie, event, sync); + SerialDevice *device = (SerialDevice *)cookie; + return device->DeSelect(event, sync); +} +#endif // DANO, HAIKU + + +/* pc_serial_close - handle close() calls */ +static status_t +pc_serial_close(void *cookie) +{ + TRACE_FUNCALLS("> pc_serial_close(0x%08x)\n", cookie); + SerialDevice *device = (SerialDevice *)cookie; + return device->Close(); +} + + +/* pc_serial_free - called after last device is closed, and all i/o complete. */ +static status_t +pc_serial_free(void *cookie) +{ + TRACE_FUNCALLS("> pc_serial_free(0x%08x)\n", cookie); + SerialDevice *device = (SerialDevice *)cookie; + acquire_sem(gDriverLock); + status_t status = device->Free(); + if (device->IsRemoved()) { + for (int32 i = 0; i < DEVICES_COUNT; i++) { + if (gSerialDevices[i] == device) { + // the device is removed already but as it was open the + // removed hook has not deleted the object + delete device; + gSerialDevices[i] = NULL; + break; + } + } + } + + release_sem(gDriverLock); + return status; +} + + +/* publish_devices - null-terminated array of devices supported by this driver. */ +const char ** +publish_devices() +{ + TRACE_FUNCALLS("> publish_devices()\n"); + for (int32 i = 0; gDeviceNames[i]; i++) + free(gDeviceNames[i]); + + int32 j = 0; + acquire_sem(gDriverLock); + for(int32 i = 0; i < DEVICES_COUNT; i++) { + if (gSerialDevices[i]) { + gDeviceNames[j] = (char *)malloc(strlen(sDeviceBaseName) + 4); + if (gDeviceNames[j]) { + sprintf(gDeviceNames[j], "%s%ld", sDeviceBaseName, i); + j++; + } else + TRACE_ALWAYS("publish_devices - no memory to allocate device names\n"); + } + } + + gDeviceNames[j] = NULL; + release_sem(gDriverLock); + return (const char **)&gDeviceNames[0]; +} + + +/* find_device - return poiter to device hooks structure for a given device */ +device_hooks * +find_device(const char *name) +{ + static device_hooks deviceHooks = { + pc_serial_open, /* -> open entry point */ + pc_serial_close, /* -> close entry point */ + pc_serial_free, /* -> free cookie */ + pc_serial_control, /* -> control entry point */ + pc_serial_read, /* -> read entry point */ + pc_serial_write, /* -> write entry point */ +#if defined(B_BEOS_VERSION_DANO) || defined(__HAIKU__) + pc_serial_select, /* -> select entry point */ + pc_serial_deselect /* -> deselect entry point */ +#endif + }; + + TRACE_FUNCALLS("> find_device(%s)\n", name); + return &deviceHooks; +} diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/Driver.h b/src/add-ons/kernel/drivers/ports/pc_serial/Driver.h new file mode 100644 index 0000000000..54ca07d199 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/pc_serial/Driver.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2007-2008 by Michael Lotz + * Heavily based on the original usb_serial driver which is: + * + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + */ +#ifndef _PC_SERIAL_DRIVER_H_ +#define _PC_SERIAL_DRIVER_H_ + +#include +#include +#include +#include + +#ifdef __HAIKU__ +#include +#else +#include "BeOSCompatibility.h" +#endif +#include "kernel_cpp.h" +#include "Tracing.h" + +extern "C" { +#include +} + +#define DRIVER_NAME "pc_serial" // driver name for debug output +#define DEVICES_COUNT 20 // max simultaneously open devices + +/* Some usefull helper defines ... */ +#define SIZEOF(array) (sizeof(array) / sizeof(array[0])) /* size of array */ +/* This one rounds the size to integral count of segs (segments) */ +#define ROUNDUP(size, seg) (((size) + (seg) - 1) & ~((seg) - 1)) +/* Default device buffer size */ +#define DEF_BUFFER_SIZE 0x200 + +/* line coding defines ... Come from CDC USB specs? */ +#define LC_STOP_BIT_1 0 +#define LC_STOP_BIT_2 2 + +#define LC_PARITY_NONE 0 +#define LC_PARITY_ODD 1 +#define LC_PARITY_EVEN 2 + +/* struct that represents line coding */ +typedef struct pc_serial_line_coding_s { + uint32 speed; + uint8 stopbits; + uint8 parity; + uint8 databits; +} pc_serial_line_coding; + +/* control line states */ +#define CLS_LINE_DTR 0x0001 +#define CLS_LINE_RTS 0x0002 + +/* attributes etc ...*/ +#ifndef USB_EP_ADDR_DIR_IN +#define USB_EP_ADDR_DIR_IN 0x80 +#define USB_EP_ADDR_DIR_OUT 0x00 +#endif + +#ifndef USB_EP_ATTR_CONTROL +#define USB_EP_ATTR_CONTROL 0x00 +#define USB_EP_ATTR_ISOCHRONOUS 0x01 +#define USB_EP_ATTR_BULK 0x02 +#define USB_EP_ATTR_INTERRUPT 0x03 +#endif + +/* USB class - communication devices */ +#define USB_DEV_CLASS_COMM 0x02 +#define USB_INT_CLASS_CDC 0x02 +#define USB_INT_SUBCLASS_ACM 0x02 +#define USB_INT_CLASS_CDC_DATA 0x0a +#define USB_INT_SUBCLASS_DATA 0x00 + +// communication device subtypes +#define FUNCTIONAL_SUBTYPE_UNION 0x06 + +extern isa_module_info *gISAModule; +extern pci_module_info *gPCIModule; +extern tty_module_info *gTTYModule; +extern struct ddomain gSerialDomain; + +extern "C" { +status_t pc_serial_device_added(pc_device device, void **cookie); +status_t pc_serial_device_removed(void *cookie); + +status_t init_hardware(); +void uninit_driver(); + +bool pc_serial_service(struct tty *ptty, struct ddrover *ddr, uint flags); + +status_t pc_serial_open(const char *name, uint32 flags, void **cookie); +status_t pc_serial_read(void *cookie, off_t position, void *buffer, size_t *numBytes); +status_t pc_serial_write(void *cookie, off_t position, const void *buffer, size_t *numBytes); +status_t pc_serial_control(void *cookie, uint32 op, void *arg, size_t length); +status_t pc_serial_select(void *cookie, uint8 event, uint32 ref, selectsync *sync); +status_t pc_serial_deselect(void *coookie, uint8 event, selectsync *sync); +status_t pc_serial_close(void *cookie); +status_t pc_serial_free(void *cookie); + +const char **publish_devices(); +device_hooks *find_device(const char *name); +} + +#endif //_PC_SERIAL_DRIVER_H_ diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/Jamfile b/src/add-ons/kernel/drivers/ports/pc_serial/Jamfile new file mode 100644 index 0000000000..cf59644608 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/pc_serial/Jamfile @@ -0,0 +1,28 @@ +SubDir HAIKU_TOP src add-ons kernel drivers ports pc_serial ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +if $(TARGET_PLATFORM_HAIKU_COMPATIBLE) { + UsePrivateKernelHeaders ; + UseHeaders [ FDirName $(HAIKU_TOP) headers os drivers tty ] : true ; +} + +SubDirC++Flags -fno-rtti ; + +KernelAddon pc_serial : + Driver.cpp + SerialDevice.cpp + Tracing.cpp +; + +#AddResources pc_serial : pc_serial.rdef ; + + +#Package haiku-pc_serial-cvs +# : +# pc_serial +# : +# boot home config add-ons kernel drivers bin ; +# +#Package haiku-pc_serial-cvs : pc_serial.settings.sample +# : boot home config settings kernel drivers sample ; diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/NOTES.txt b/src/add-ons/kernel/drivers/ports/pc_serial/NOTES.txt new file mode 100644 index 0000000000..08cc2aa72e --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/pc_serial/NOTES.txt @@ -0,0 +1,4 @@ + +references: +http://www.beyondlogic.org/serial/serial.htm + diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp new file mode 100644 index 0000000000..ccd520a465 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp @@ -0,0 +1,713 @@ +/* + * Copyright (c) 2007-2008 by Michael Lotz + * Heavily based on the original usb_serial driver which is: + * + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + */ +#include "SerialDevice.h" +#include "USB3.h" + +#include "ACM.h" +#include "FTDI.h" +#include "KLSI.h" +#include "Prolific.h" + +SerialDevice::SerialDevice(usb_device device, uint16 vendorID, + uint16 productID, const char *description) + : fDevice(device), + fVendorID(vendorID), + fProductID(productID), + fDescription(description), + fDeviceOpen(false), + fDeviceRemoved(false), + fControlPipe(0), + fReadPipe(0), + fWritePipe(0), + fBufferArea(-1), + fReadBuffer(NULL), + fReadBufferSize(ROUNDUP(DEF_BUFFER_SIZE, 16)), + fWriteBuffer(NULL), + fWriteBufferSize(ROUNDUP(DEF_BUFFER_SIZE, 16)), + fInterruptBuffer(NULL), + fInterruptBufferSize(16), + fDoneRead(-1), + fDoneWrite(-1), + fControlOut(0), + fInputStopped(false), + fDeviceThread(-1), + fStopDeviceThread(false) +{ + memset(&fTTYFile, 0, sizeof(ttyfile)); + memset(&fTTY, 0, sizeof(tty)); +} + + +SerialDevice::~SerialDevice() +{ + Removed(); + + if (fDoneRead >= B_OK) + delete_sem(fDoneRead); + if (fDoneWrite >= B_OK) + delete_sem(fDoneWrite); + + if (fBufferArea >= B_OK) + delete_area(fBufferArea); + + mutex_destroy(&fReadLock); + mutex_destroy(&fWriteLock); +} + + +status_t +SerialDevice::Init() +{ + 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 + 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; + fInterruptBuffer = fWriteBuffer + fWriteBufferSize; + return B_OK; +} + + +void +SerialDevice::SetControlPipe(usb_pipe handle) +{ + fControlPipe = handle; +} + + +void +SerialDevice::SetReadPipe(usb_pipe handle) +{ + fReadPipe = handle; +} + + +void +SerialDevice::SetWritePipe(usb_pipe handle) +{ + fWritePipe = handle; +} + + +void +SerialDevice::SetModes() +{ + struct termios tios; + memcpy(&tios, &fTTY.t, sizeof(struct termios)); + 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 + }; + + uint32 baudCount = sizeof(baudRates) / sizeof(baudRates[0]); + uint32 baudIndex = tios.c_cflag & CBAUD; + if (baudIndex > baudCount) + baudIndex = baudCount - 1; + + usb_serial_line_coding lineCoding; + lineCoding.speed = baudRates[baudIndex]; + lineCoding.stopbits = (tios.c_cflag & CSTOPB) ? LC_STOP_BIT_2 : LC_STOP_BIT_1; + + if (tios.c_cflag & PARENB) { + lineCoding.parity = LC_PARITY_EVEN; + if (tios.c_cflag & PARODD) + lineCoding.parity = LC_PARITY_ODD; + } else + lineCoding.parity = LC_PARITY_NONE; + + lineCoding.databits = (tios.c_cflag & CS8) ? 8 : 7; + + if (lineCoding.speed == 0) { + newControl &= 0xfffffffe; + lineCoding.speed = fLineCoding.speed; + } else + newControl = CLS_LINE_DTR; + + if (fControlOut != newControl) { + fControlOut = newControl; + TRACE("newctrl send to modem: 0x%08x\n", newControl); + SetControlLineState(newControl); + } + + if (memcmp(&lineCoding, &fLineCoding, sizeof(usb_serial_line_coding)) != 0) { + fLineCoding.speed = lineCoding.speed; + fLineCoding.stopbits = lineCoding.stopbits; + fLineCoding.databits = lineCoding.databits; + fLineCoding.parity = lineCoding.parity; + TRACE("send to modem: speed %d sb: 0x%08x db: 0x%08x parity: 0x%08x\n", + fLineCoding.speed, fLineCoding.stopbits, fLineCoding.databits, + fLineCoding.parity); + SetLineCoding(&fLineCoding); + } +} + + +bool +SerialDevice::Service(struct tty *ptty, struct ddrover *ddr, uint flags) +{ + if (&fTTY != ptty) + return false; + + if (flags <= TTYGETSIGNALS) { + switch (flags) { + case TTYENABLE: + TRACE("TTYENABLE\n"); + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, false); + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, true); + fControlOut = CLS_LINE_DTR | CLS_LINE_RTS; + SetControlLineState(fControlOut); + break; + + case TTYDISABLE: + TRACE("TTYDISABLE\n"); + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, false); + fControlOut = 0x0; + SetControlLineState(fControlOut); + break; + + case TTYISTOP: + TRACE("TTYISTOP\n"); + fInputStopped = true; + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, false); + break; + + case TTYIRESUME: + TRACE("TTYIRESUME\n"); + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, true); + fInputStopped = false; + break; + + case TTYGETSIGNALS: + TRACE("TTYGETSIGNALS\n"); + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, true); + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, true); + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDSR, false); + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWRI, false); + break; + + case TTYSETMODES: + TRACE("TTYSETMODES\n"); + SetModes(); + break; + + case TTYOSTART: + case TTYOSYNC: + case TTYSETBREAK: + case TTYCLRBREAK: + case TTYSETDTR: + case TTYCLRDTR: + TRACE("TTY other\n"); + break; + } + + return true; + } + + return false; +} + + +status_t +SerialDevice::Open(uint32 flags) +{ + if (fDeviceOpen) + return B_BUSY; + + if (fDeviceRemoved) + return B_DEV_NOT_READY; + + gTTYModule->ttyinit(&fTTY, true); + fTTYFile.tty = &fTTY; + fTTYFile.flags = flags; + ResetDevice(); + + struct ddrover *ddr = gTTYModule->ddrstart(NULL); + if (!ddr) + return B_NO_MEMORY; + + gTTYModule->ddacquire(ddr, &gSerialDomain); + status_t status = gTTYModule->ttyopen(&fTTYFile, ddr, usb_serial_service); + gTTYModule->ddrdone(ddr); + + if (status < B_OK) { + TRACE_ALWAYS("open: failed to open tty\n"); + return status; + } + + fDeviceThread = spawn_kernel_thread(DeviceThread, "usb_serial device thread", + B_NORMAL_PRIORITY, this); + + if (fDeviceThread < B_OK) { + TRACE_ALWAYS("open: failed to spawn kernel thread\n"); + return fDeviceThread; + } + + resume_thread(fDeviceThread); + + fControlOut = CLS_LINE_DTR | CLS_LINE_RTS; + SetControlLineState(fControlOut); + + status = gUSBModule->queue_interrupt(fControlPipe, fInterruptBuffer, + fInterruptBufferSize, InterruptCallbackFunction, this); + if (status < B_OK) + TRACE_ALWAYS("failed to queue initial interrupt\n"); + + fDeviceOpen = true; + return B_OK; +} + + +status_t +SerialDevice::Read(char *buffer, size_t *numBytes) +{ + if (fDeviceRemoved) { + *numBytes = 0; + 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; + } + + struct ddrover *ddr = gTTYModule->ddrstart(NULL); + if (!ddr) { + *numBytes = 0; + mutex_unlock(&fReadLock); + return B_NO_MEMORY; + } + + status = gTTYModule->ttyread(&fTTYFile, ddr, buffer, numBytes); + gTTYModule->ddrdone(ddr); + + mutex_unlock(&fReadLock); + return status; +} + + +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); + 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; +} + + +status_t +SerialDevice::Control(uint32 op, void *arg, size_t length) +{ + if (fDeviceRemoved) + return B_DEV_NOT_READY; + + struct ddrover *ddr = gTTYModule->ddrstart(NULL); + if (!ddr) + return B_NO_MEMORY; + + status_t status = gTTYModule->ttycontrol(&fTTYFile, ddr, op, arg, length); + gTTYModule->ddrdone(ddr); + return status; +} + + +status_t +SerialDevice::Select(uint8 event, uint32 ref, selectsync *sync) +{ + if (fDeviceRemoved) + return B_DEV_NOT_READY; + + struct ddrover *ddr = gTTYModule->ddrstart(NULL); + if (!ddr) + return B_NO_MEMORY; + + status_t status = gTTYModule->ttyselect(&fTTYFile, ddr, event, ref, sync); + gTTYModule->ddrdone(ddr); + return status; +} + + +status_t +SerialDevice::DeSelect(uint8 event, selectsync *sync) +{ + if (fDeviceRemoved) + return B_DEV_NOT_READY; + + struct ddrover *ddr = gTTYModule->ddrstart(NULL); + if (!ddr) + return B_NO_MEMORY; + + status_t status = gTTYModule->ttydeselect(&fTTYFile, ddr, event, sync); + gTTYModule->ddrdone(ddr); + return status; +} + + +status_t +SerialDevice::Close() +{ + OnClose(); + + if (!fDeviceRemoved) { + gUSBModule->cancel_queued_transfers(fReadPipe); + gUSBModule->cancel_queued_transfers(fWritePipe); + gUSBModule->cancel_queued_transfers(fControlPipe); + } + + struct ddrover *ddr = gTTYModule->ddrstart(NULL); + if (!ddr) + return B_NO_MEMORY; + + status_t status = gTTYModule->ttyclose(&fTTYFile, ddr); + gTTYModule->ddrdone(ddr); + + fDeviceOpen = false; + return status; +} + + +status_t +SerialDevice::Free() +{ + struct ddrover *ddr = gTTYModule->ddrstart(NULL); + if (!ddr) + return B_NO_MEMORY; + + status_t status = gTTYModule->ttyfree(&fTTYFile, ddr); + gTTYModule->ddrdone(ddr); + return status; +} + + +void +SerialDevice::Removed() +{ + if (fDeviceRemoved) + return; + + // notifies us that the device was removed + fDeviceRemoved = true; + + // we need to ensure that we do not use the device anymore + fStopDeviceThread = 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; + + mutex_lock(&fWriteLock); + mutex_unlock(&fWriteLock); +} + + +status_t +SerialDevice::AddDevice(const usb_configuration_info *config) +{ + // default implementation - does nothing + return B_ERROR; +} + + +status_t +SerialDevice::ResetDevice() +{ + // default implementation - does nothing + return B_OK; +} + + +status_t +SerialDevice::SetLineCoding(usb_serial_line_coding *coding) +{ + // default implementation - does nothing + return B_OK; +} + + +status_t +SerialDevice::SetControlLineState(uint16 state) +{ + // default implementation - does nothing + return B_OK; +} + + +void +SerialDevice::OnRead(char **buffer, size_t *numBytes) +{ + // default implementation - does nothing +} + + +void +SerialDevice::OnWrite(const char *buffer, size_t *numBytes, size_t *packetBytes) +{ + // default implementation - does nothing +} + + +void +SerialDevice::OnClose() +{ + // default implementation - does nothing +} + + +int32 +SerialDevice::DeviceThread(void *data) +{ + SerialDevice *device = (SerialDevice *)data; + + while (!device->fStopDeviceThread) { + status_t status = gUSBModule->queue_bulk(device->fReadPipe, + device->fReadBuffer, device->fReadBufferSize, + device->ReadCallbackFunction, data); + if (status < B_OK) { + TRACE_ALWAYS("device thread: queueing failed with error: 0x%08x\n", status); + break; + } + + 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", status); + break; + } + + if (device->fStatusRead != B_OK) { + TRACE("device 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; + } + } + + char *buffer = device->fReadBuffer; + size_t readLength = device->fActualLengthRead; + device->OnRead(&buffer, &readLength); + if (readLength == 0) + continue; + + ddrover *ddr = gTTYModule->ddrstart(NULL); + if (!ddr) { + TRACE_ALWAYS("device thread: ddrstart problem\n"); + return B_NO_MEMORY; + } + + while (device->fInputStopped) + snooze(100); + + gTTYModule->ttyilock(&device->fTTY, ddr, true); + for (size_t i = 0; i < readLength; i++) + gTTYModule->ttyin(&device->fTTY, ddr, buffer[i]); + + gTTYModule->ttyilock(&device->fTTY, ddr, false); + gTTYModule->ddrdone(ddr); + } + + return B_OK; +} + + +void +SerialDevice::ReadCallbackFunction(void *cookie, int32 status, void *data, + uint32 actualLength) +{ + TRACE_FUNCALLS("read callback: cookie: 0x%08x status: 0x%08x data: 0x%08x len: %lu\n", + cookie, status, data, actualLength); + + SerialDevice *device = (SerialDevice *)cookie; + device->fActualLengthRead = actualLength; + device->fStatusRead = status; + release_sem_etc(device->fDoneRead, 1, B_DO_NOT_RESCHEDULE); +} + + +void +SerialDevice::WriteCallbackFunction(void *cookie, int32 status, void *data, + uint32 actualLength) +{ + TRACE_FUNCALLS("write callback: cookie: 0x%08x status: 0x%08x data: 0x%08x len: %lu\n", + cookie, status, data, actualLength); + + SerialDevice *device = (SerialDevice *)cookie; + device->fActualLengthWrite = actualLength; + device->fStatusWrite = status; + release_sem_etc(device->fDoneWrite, 1, B_DO_NOT_RESCHEDULE); +} + + +void +SerialDevice::InterruptCallbackFunction(void *cookie, int32 status, + void *data, uint32 actualLength) +{ + TRACE_FUNCALLS("interrupt callback: cookie: 0x%08x status: 0x%08x data: 0x%08x len: %lu\n", + cookie, status, data, actualLength); + + SerialDevice *device = (SerialDevice *)cookie; + device->fActualLengthInterrupt = actualLength; + device->fStatusInterrupt = status; + + // ToDo: maybe handle those somehow? + + if (status == B_OK && !device->fDeviceRemoved) { + status = gUSBModule->queue_interrupt(device->fControlPipe, + device->fInterruptBuffer, device->fInterruptBufferSize, + device->InterruptCallbackFunction, device); + } +} + + + +SerialDevice * +SerialDevice::MakeDevice(usb_device device, uint16 vendorID, + uint16 productID) +{ + const char *description = NULL; + + switch (vendorID) { + case VENDOR_IODATA: + case VENDOR_ATEN: + case VENDOR_TDK: + case VENDOR_RATOC: + case VENDOR_PROLIFIC: + case VENDOR_ELECOM: + case VENDOR_SOURCENEXT: + case VENDOR_HAL: + { + switch (productID) { + case PRODUCT_PROLIFIC_RSAQ2: description = "PL2303 Serial adapter (IODATA USB-RSAQ2)"; break; + case PRODUCT_IODATA_USBRSAQ: description = "I/O Data USB serial adapter USB-RSAQ1"; break; + case PRODUCT_ATEN_UC232A: description = "Aten Serial adapter"; break; + case PRODUCT_TDK_UHA6400: description = "TDK USB-PHS Adapter UHA6400"; break; + case PRODUCT_RATOC_REXUSB60: description = "Ratoc USB serial adapter REX-USB60"; break; + case PRODUCT_PROLIFIC_PL2303: description = "PL2303 Serial adapter (ATEN/IOGEAR UC232A)"; break; + case PRODUCT_ELECOM_UCSGT: description = "Elecom UC-SGT"; break; + case PRODUCT_SOURCENEXT_KEIKAI8: description = "SOURCENEXT KeikaiDenwa 8"; break; + case PRODUCT_SOURCENEXT_KEIKAI8_CHG: description = "SOURCENEXT KeikaiDenwa 8 with charger"; break; + case PRODUCT_HAL_IMR001: description = "HAL Corporation Crossam2+USB"; break; + } + + if (!description) + break; + + return new ProlificDevice(device, vendorID, productID, description); + } + + case VENDOR_FTDI: + { + switch (productID) { + case PRODUCT_FTDI_8U100AX: description = "FTDI 8U100AX serial converter"; break; + case PRODUCT_FTDI_8U232AM: description = "FTDI 8U232AM serial converter"; break; + } + + if (!description) + break; + + return new FTDIDevice(device, vendorID, productID, description); + } + + case VENDOR_PALM: + case VENDOR_KLSI: + { + switch (productID) { + case PRODUCT_PALM_CONNECT: description = "PalmConnect RS232"; break; + case PRODUCT_KLSI_KL5KUSB105D: description = "KLSI KL5KUSB105D"; break; + } + + if (!description) + break; + + return new KLSIDevice(device, vendorID, productID, description); + } + } + + return new ACMDevice(device, vendorID, productID, "CDC ACM compatible device"); +} diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h new file mode 100644 index 0000000000..085102faf1 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2007-2008 by Michael Lotz + * Heavily based on the original usb_serial driver which is: + * + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + */ +#ifndef _SERIAL_DEVICE_H_ +#define _SERIAL_DEVICE_H_ + +#include "Driver.h" + +class SerialDevice { +public: + SerialDevice(usb_device device, + uint16 vendorID, uint16 productID, + const char *description); +virtual ~SerialDevice(); + +static SerialDevice * MakeDevice(usb_device device, uint16 vendorID, + uint16 productID); + + status_t Init(); + + usb_device Device() { return fDevice; }; + uint16 ProductID() { return fProductID; }; + uint16 VendorID() { return fVendorID; }; + const char * Description() { return fDescription; }; + + void SetControlPipe(usb_pipe handle); + usb_pipe ControlPipe() { return fControlPipe; }; + + void SetReadPipe(usb_pipe handle); + usb_pipe ReadPipe() { return fReadPipe; }; + + void SetWritePipe(usb_pipe handle); + usb_pipe WritePipe() { return fWritePipe; } + + char * ReadBuffer() { return fReadBuffer; }; + size_t ReadBufferSize() { return fReadBufferSize; }; + + char * WriteBuffer() { return fWriteBuffer; }; + size_t WriteBufferSize() { return fWriteBufferSize; }; + + void SetModes(); + bool Service(struct tty *ptty, struct ddrover *ddr, + uint flags); + + status_t Open(uint32 flags); + status_t Read(char *buffer, size_t *numBytes); + status_t Write(const char *buffer, size_t *numBytes); + status_t Control(uint32 op, void *arg, size_t length); + status_t Select(uint8 event, uint32 ref, selectsync *sync); + status_t DeSelect(uint8 event, selectsync *sync); + status_t Close(); + status_t Free(); + + bool IsOpen() { return fDeviceOpen; }; + void Removed(); + bool IsRemoved() { return fDeviceRemoved; }; + + /* virtual interface to be overriden as necessary */ +virtual status_t AddDevice(const usb_configuration_info *config); + +virtual status_t ResetDevice(); + +virtual status_t SetLineCoding(usb_serial_line_coding *coding); +virtual status_t SetControlLineState(uint16 state); + +virtual void OnRead(char **buffer, size_t *numBytes); +virtual void OnWrite(const char *buffer, size_t *numBytes, + size_t *packetBytes); +virtual void OnClose(); + +protected: + 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 void ReadCallbackFunction(void *cookie, + int32 status, void *data, + uint32 actualLength); +static void WriteCallbackFunction(void *cookie, + int32 status, void *data, + uint32 actualLength); +static void InterruptCallbackFunction(void *cookie, + int32 status, void *data, + uint32 actualLength); + + usb_device fDevice; // USB device handle + uint16 fVendorID; + uint16 fProductID; + const char * fDescription; // informational description + bool fDeviceOpen; + bool fDeviceRemoved; + + /* communication pipes */ + usb_pipe fControlPipe; + usb_pipe fReadPipe; + usb_pipe fWritePipe; + + /* line coding */ + usb_serial_line_coding fLineCoding; + + /* data buffers */ + area_id fBufferArea; + char * fReadBuffer; + size_t fReadBufferSize; + char * fWriteBuffer; + size_t fWriteBufferSize; + char * fInterruptBuffer; + size_t fInterruptBufferSize; + + /* variables used in callback functionality */ + size_t fActualLengthRead; + uint32 fStatusRead; + size_t fActualLengthWrite; + uint32 fStatusWrite; + size_t fActualLengthInterrupt; + uint32 fStatusInterrupt; + + /* semaphores used in callbacks */ + sem_id fDoneRead; + sem_id fDoneWrite; + + uint16 fControlOut; + bool fInputStopped; + struct ttyfile fTTYFile; + struct tty fTTY; + + /* device thread management */ + thread_id fDeviceThread; + bool fStopDeviceThread; + + /* device locks to ensure no concurent reads/writes */ + mutex fReadLock; + mutex fWriteLock; +}; + +#endif // _SERIAL_DEVICE_H_ diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/Tracing.cpp b/src/add-ons/kernel/drivers/ports/pc_serial/Tracing.cpp new file mode 100644 index 0000000000..993efb72e7 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/pc_serial/Tracing.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2007-2008 by Michael Lotz + * Heavily based on the original usb_serial driver which is: + * + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + */ +#include "Tracing.h" +#include "Driver.h" +#include "USB3.h" + +#include //sprintf +#include //posix file i/o - create, write, close +#include +#include + + +#if DEBUG +bool gLogEnabled = true; +#else +bool gLogEnabled = false; +#endif + +bool gLogToFile = false; +bool gLogAppend = false; +bool gLogFunctionCalls = false; +bool gLogFunctionReturns = false; +bool gLogFunctionResults = false; + +static const char *sLogFilePath="/boot/home/"DRIVER_NAME".log"; +static sem_id sLogLock; + + +void +load_settings() +{ + void *settingsHandle; + settingsHandle = load_driver_settings(DRIVER_NAME); + +#if !DEBUG + gLogEnabled = get_driver_boolean_parameter(settingsHandle, + "debug_output", gLogEnabled, true); +#endif + + gLogToFile = get_driver_boolean_parameter(settingsHandle, + "debug_output_in_file", gLogToFile, true); + gLogAppend = !get_driver_boolean_parameter(settingsHandle, + "debug_output_file_rewrite", !gLogAppend, true); + gLogFunctionCalls = get_driver_boolean_parameter(settingsHandle, + "debug_trace_func_calls", gLogFunctionCalls, false); + gLogFunctionReturns = get_driver_boolean_parameter(settingsHandle, + "debug_trace_func_returns", gLogFunctionReturns, false); + gLogFunctionResults = get_driver_boolean_parameter(settingsHandle, + "debug_trace_func_results", gLogFunctionResults, false); + + unload_driver_settings(settingsHandle); +} + + +void +create_log_file() +{ + if(!gLogToFile) + return; + + int flags = O_WRONLY | O_CREAT | (!gLogAppend ? O_TRUNC : 0); + close(open(sLogFilePath, flags, 0666)); + sLogLock = create_sem(1, DRIVER_NAME"-logging"); +} + + +void +usb_serial_trace(bool force, char *format, ...) +{ + if (!gLogEnabled && !force) + return; + + static char buffer[1024]; + char *bufferPointer = buffer; + if (!gLogToFile) { + const char *prefix = "\33[32m"DRIVER_NAME":\33[0m "; + strcpy(bufferPointer, prefix); + bufferPointer += strlen(prefix); + } + + va_list argumentList; + va_start(argumentList, format); + vsprintf(bufferPointer, format, argumentList); + va_end(argumentList); + + if (gLogToFile) { + acquire_sem(sLogLock); + int fd = open(sLogFilePath, O_WRONLY | O_APPEND); + write(fd, buffer, strlen(buffer)); + close(fd); + release_sem(sLogLock); + } else + dprintf(buffer); +} + + +void +trace_ddomain(struct ddomain *dd) +{ + TRACE("struct ddomain:\n" + "\tddrover: 0x%08x\n" + "\tbg: %d, locked: %d\n", dd->r, dd->bg, dd->locked); +} + + +void +trace_termios(struct termios *tios) +{ + TRACE("struct termios:\n" + "\tc_iflag: 0x%08x\n" + "\tc_oflag: 0x%08x\n" + "\tc_cflag: 0x%08x\n" + "\tc_lflag: 0x%08x\n" + "\tc_line: 0x%08x\n" +// "\tc_ixxxxx: 0x%08x\n" +// "\tc_oxxxxx: 0x%08x\n" + "\tc_cc[0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x]\n", + tios->c_iflag, tios->c_oflag, tios->c_cflag, tios->c_lflag, + tios->c_line, +// tios->c_ixxxxx, tios->c_oxxxxx, + tios->c_cc[0], tios->c_cc[1], tios->c_cc[2], tios->c_cc[3], + tios->c_cc[4], tios->c_cc[5], tios->c_cc[6], tios->c_cc[7], + tios->c_cc[8], tios->c_cc[9], tios->c_cc[10]); +} + + +void +trace_str(struct str *str) +{ + TRACE("struct str:\n" + "\tbuffer: 0x%08x\n" + "\tbufsize: %d\n" + "\tcount: %d\n" + "\ttail: %d\n" + "\tallocated: %d\n", + str->buffer, str->bufsize, str->count, str->tail, str->allocated); +} + + +void +trace_winsize(struct winsize *ws) +{ + TRACE("struct winsize:\n" + "\tws_row: %d\n" + "\tws_col: %d\n" + "\tws_xpixel: %d\n" + "\tws_ypixel: %d\n", + ws->ws_row, ws->ws_col, ws->ws_xpixel, ws->ws_ypixel); +} + + +void +trace_tty(struct tty *tty) +{ + TRACE("struct tty:\n" + "\tnopen: %d, flags: 0x%08x,\n", tty->nopen, tty->flags); + + TRACE("ddomain dd:\n"); + trace_ddomain(&tty->dd); + TRACE("ddomain ddi:\n"); + trace_ddomain(&tty->ddi); + + TRACE("\tpgid: %08x\n", tty->pgid); + TRACE("termios t:"); + trace_termios(&tty->t); + + TRACE("\tiactivity: %d, ibusy: %d\n", tty->iactivity, tty->ibusy); + + TRACE("str istr:\n"); + trace_str(&tty->istr); + TRACE("str rstr:\n"); + trace_str(&tty->rstr); + TRACE("str ostr:\n"); + trace_str(&tty->ostr); + + TRACE("winsize wsize:\n"); + trace_winsize(&tty->wsize); + + TRACE("\tservice: 0x%08x\n", tty->service); +} diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/Tracing.h b/src/add-ons/kernel/drivers/ports/pc_serial/Tracing.h new file mode 100644 index 0000000000..65af5c5525 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/pc_serial/Tracing.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2007-2008 by Michael Lotz + * Heavily based on the original usb_serial driver which is: + * + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + */ +#ifndef _USB_SERIAL_TRACING_H_ +#define _USB_SERIAL_TRACING_H_ + +void load_settings(); +void create_log_file(); +void usb_serial_trace(bool force, char *format, ...); + +#define TRACE_ALWAYS(x...) usb_serial_trace(true, x); +#define TRACE(x...) usb_serial_trace(false, x); + +extern bool gLogFunctionCalls; +#define TRACE_FUNCALLS(x...) \ + if (gLogFunctionCalls) \ + usb_serial_trace(false, x); + +extern bool gLogFunctionReturns; +#define TRACE_FUNCRET(x...) \ + if (gLogFunctionReturns) \ + usb_serial_trace(false, x); + +extern bool gLogFunctionResults; +#define TRACE_FUNCRES(func, param) \ + if (gLogFunctionResults) \ + func(param); + +void trace_ddomain(struct ddomain *dd); +void trace_termios(struct termios *tios); +void trace_str(struct str *str); +void trace_winsize(struct winsize *ws); +void trace_tty(struct tty *tty); + +#endif //_USB_SERIAL_TRACING_H_ diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/kernel_cpp.h b/src/add-ons/kernel/drivers/ports/pc_serial/kernel_cpp.h new file mode 100644 index 0000000000..7d7b025872 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/pc_serial/kernel_cpp.h @@ -0,0 +1,45 @@ +#ifndef _KERNEL_CPP_H_ +#define _KERNEL_CPP_H_ + +#include + +inline void * +operator new(size_t size) +{ + return malloc(size); +} + + +inline void * +operator new[](size_t size) +{ + return malloc(size); +} + + +inline void +operator delete(void *pointer) +{ + free(pointer); +} + + +inline void +operator delete[](void *pointer) +{ + free(pointer); +} + + +inline void +terminate(void) +{ +} + + +static inline void +__throw() +{ +} + +#endif // _KERNEL_CPP_H_