diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/ACM.cpp b/src/add-ons/kernel/drivers/ports/usb_serial/ACM.cpp new file mode 100644 index 0000000000..33a0edf825 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/ACM.cpp @@ -0,0 +1,120 @@ +/* + * 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 "ACM.h" +#include "Driver.h" + +ACMDevice::ACMDevice(usb_device device, uint16 vendorID, uint16 productID, + const char *description) + : SerialDevice(device, vendorID, productID, description) +{ +} + + +status_t +ACMDevice::AddDevice(const usb_configuration_info *config) +{ + TRACE_FUNCALLS("> ACMDevice::AddDevice(0x%08x, 0x%08x)\n", this, config); + + status_t status = ENODEV; + uint8 masterIndex = 0; + uint8 slaveIndex = 0; + for (size_t i = 0; i < config->interface_count && status < B_OK; i++) { + usb_interface_info *interface = config->interface[i].active; + usb_interface_descriptor *descriptor = interface->descr; + if (descriptor->interface_class == USB_INT_CLASS_CDC + && descriptor->interface_subclass == USB_INT_SUBCLASS_ACM + && interface->generic_count > 0) { + // try to find and interpret the union functional descriptor + for (size_t j = 0; j < interface->generic_count; j++) { + usb_generic_descriptor *generic = &interface->generic[j]->generic; + if (generic->length >= 5 + && generic->data[0] == FUNCTIONAL_SUBTYPE_UNION) { + masterIndex = generic->data[1]; + slaveIndex = generic->data[2]; + status = B_OK; + break; + } + } + } + } + + if (status == B_OK && masterIndex < config->interface_count) { + // check that the indicated master interface fits our need + usb_interface_info *interface = config->interface[masterIndex].active; + usb_interface_descriptor *descriptor = interface->descr; + if ((descriptor->interface_class == USB_INT_CLASS_CDC + || descriptor->interface_class == USB_INT_CLASS_CDC_DATA) + && interface->endpoint_count >= 1) { + SetControlPipe(interface->endpoint[0].handle); + } else + status = ENODEV; + } + + if (status == B_OK && slaveIndex < config->interface_count) { + // check that the indicated slave interface fits our need + usb_interface_info *interface = config->interface[slaveIndex].active; + usb_interface_descriptor *descriptor = interface->descr; + if (descriptor->interface_class == USB_INT_CLASS_CDC_DATA + && interface->endpoint_count >= 2) { + if (!(interface->endpoint[0].descr->endpoint_address & USB_EP_ADDR_DIR_IN)) + SetWritePipe(interface->endpoint[0].handle); + else + SetReadPipe(interface->endpoint[0].handle); + + if (interface->endpoint[1].descr->endpoint_address & USB_EP_ADDR_DIR_IN) + SetReadPipe(interface->endpoint[1].handle); + else + SetWritePipe(interface->endpoint[1].handle); + } else + status = ENODEV; + } + + TRACE_FUNCRET("< ACMDevice::AddDevice() returns: 0x%08x\n", status); + return status; +} + + +status_t +ACMDevice::SetLineCoding(usb_serial_line_coding *lineCoding) +{ + TRACE_FUNCALLS("> ACMDevice::SetLineCoding(0x%08x, {%d, 0x%02x, 0x%02x, 0x%02x})\n", + this, lineCoding->speed, lineCoding->stopbits, lineCoding->parity, + lineCoding->databits); + + size_t length = 0; + status_t status = gUSBModule->send_request(Device(), + USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, + SET_LINE_CODING, 0, 0, + sizeof(usb_serial_line_coding), + lineCoding, &length); + + TRACE_FUNCRET("< ACMDevice::SetLineCoding() returns: 0x%08x\n", status); + return status; +} + + +status_t +ACMDevice::SetControlLineState(uint16 state) +{ + TRACE_FUNCALLS("> ACMDevice::SetControlLineState(0x%08x, 0x%04x)\n", this, state); + + size_t length = 0; + status_t status = gUSBModule->send_request(Device(), + USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, + SET_CONTROL_LINE_STATE, state, 0, 0, NULL, &length); + + TRACE_FUNCRET("< ACMDevice::SetControlLineState() returns: 0x%08x\n", status); + return status; +} + + +void +ACMDevice::OnWrite(const char *buffer, size_t *numBytes) +{ + memcpy(WriteBuffer(), buffer, *numBytes); +} diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/ACM.h b/src/add-ons/kernel/drivers/ports/usb_serial/ACM.h new file mode 100644 index 0000000000..8be4498674 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/ACM.h @@ -0,0 +1,36 @@ +/* + * 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_ACM_H_ +#define _USB_ACM_H_ + +#include "SerialDevice.h" + +/* requests for CDC ACM devices */ +#define SEND_ENCAPSULATED_COMMAND 0x00 +#define GET_ENCAPSULATED_RESPONSE 0x01 +#define SET_LINE_CODING 0x20 +#define SET_CONTROL_LINE_STATE 0x22 + +/* notifications for CDC ACM devices */ +#define NETWORK_CONNECTION 0x00 +#define RESPONSE_AVAILABLE 0x01 + +class ACMDevice : public SerialDevice { +public: + ACMDevice(usb_device device, uint16 vendorID, + uint16 productID, const char *description); + +virtual status_t AddDevice(const usb_configuration_info *config); + +virtual status_t SetLineCoding(usb_serial_line_coding *coding); +virtual status_t SetControlLineState(uint16 state); + +virtual void OnWrite(const char *buffer, size_t *numBytes); +}; + +#endif //_USB_ACM_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/BeOSCompatibility.h b/src/add-ons/kernel/drivers/ports/usb_serial/BeOSCompatibility.h new file mode 100644 index 0000000000..9dd335d1e4 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/BeOSCompatibility.h @@ -0,0 +1,54 @@ +#ifndef _BEOS_COMPATIBILITY_H_ +#define _BEOS_COMPATIBILITY_H_ +#ifndef HAIKU_TARGET_PLATFORM_HAIKU + +typedef struct benaphore { + sem_id sem; + int32 count; +} benaphore; + + +static inline status_t +benaphore_init(benaphore *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 +benaphore_destroy(benaphore *ben) +{ + delete_sem(ben->sem); + ben->sem = -1; +} + + +static inline status_t +benaphore_lock(benaphore *ben) +{ + if (atomic_add(&ben->count, -1) <= 0) + return acquire_sem(ben->sem); + + return B_OK; +} + + +static inline status_t +benaphore_unlock(benaphore *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/usb_serial/Driver.cpp b/src/add-ons/kernel/drivers/ports/usb_serial/Driver.cpp new file mode 100644 index 0000000000..6d93ae5ddf --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/Driver.cpp @@ -0,0 +1,347 @@ +/* + * 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" +#include "USB3.h" + +static const char *sDeviceBaseName = "ports/usb"; +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 +usb_serial_device_added(usb_device device, void **cookie) +{ + TRACE_FUNCALLS("> usb_serial_device_added(0x%08x, 0x%08x)\n", device, cookie); + + status_t status = B_OK; + const usb_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 usb_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 +usb_serial_device_removed(void *cookie) +{ + TRACE_FUNCALLS("> usb_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) { + delete device; + gSerialDevices[i] = NULL; + break; + } + } + + release_sem(gDriverLock); + TRACE_FUNCRET("< usb_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] = 0; + + gDeviceNames[0] = NULL; + //load_driver_symbols(DRIVER_NAME); + + 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 usb_notify_hooks notifyHooks = { + &usb_serial_device_added, + &usb_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 +usb_serial_service(struct tty *ptty, struct ddrover *ddr, uint flags) +{ + TRACE_FUNCALLS("> usb_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("< usb_serial_service() returns: true\n"); + return true; + } + } + + TRACE_FUNCRET("< usb_serial_service() returns: false\n"); + return false; +} + + +/* usb_serial_open - handle open() calls */ +static status_t +usb_serial_open(const char *name, uint32 flags, void **cookie) +{ + TRACE_FUNCALLS("> usb_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("< usb_serial_open() returns: 0x%08x\n", status); + return status; +} + + +/* usb_serial_read - handle read() calls */ +static status_t +usb_serial_read(void *cookie, off_t position, void *buffer, size_t *numBytes) +{ + TRACE_FUNCALLS("> usb_serial_read(0x%08x, %Ld, 0x%08x, %d)\n", cookie, + position, buffer, *numBytes); + SerialDevice *device = (SerialDevice *)cookie; + return device->Read((char *)buffer, numBytes); +} + + +/* usb_serial_write - handle write() calls */ +static status_t +usb_serial_write(void *cookie, off_t position, const void *buffer, + size_t *numBytes) +{ + TRACE_FUNCALLS("> usb_serial_write(0x%08x, %Ld, 0x%08x, %d)\n", cookie, + position, buffer, *numBytes); + SerialDevice *device = (SerialDevice *)cookie; + return device->Write((const char *)buffer, numBytes); +} + + +/* usb_serial_control - handle ioctl calls */ +static status_t +usb_serial_control(void *cookie, uint32 op, void *arg, size_t length) +{ + TRACE_FUNCALLS("> usb_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__) +/* usb_serial_select - handle select start */ +static status_t +usb_serial_select(void *cookie, uint8 event, uint32 ref, selectsync *sync) +{ + TRACE_FUNCALLS("> usb_serial_select(0x%08x, 0x%08x, 0x%08x, %p)\n", + cookie, event, ref, sync); + SerialDevice *device = (SerialDevice *)cookie; + return device->Select(event, ref, sync); +} + + +/* usb_serial_deselect - handle select exit */ +static status_t +usb_serial_deselect(void *cookie, uint8 event, selectsync *sync) +{ + TRACE_FUNCALLS("> usb_serial_deselect(0x%08x, 0x%08x, %p)\n", + cookie, event, sync); + SerialDevice *device = (SerialDevice *)cookie; + return device->DeSelect(event, sync); +} +#endif // DANO, HAIKU + + +/* usb_serial_close - handle close() calls */ +static status_t +usb_serial_close(void *cookie) +{ + TRACE_FUNCALLS("> usb_serial_close(0x%08x)\n", cookie); + SerialDevice *device = (SerialDevice *)cookie; + return device->Close(); +} + + +/* usb_serial_free - called after last device is closed, and all i/o complete. */ +static status_t +usb_serial_free(void *cookie) +{ + TRACE_FUNCALLS("> usb_serial_free(0x%08x)\n", cookie); + SerialDevice *device = (SerialDevice *)cookie; + return device->Free(); +} + + +/* 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 = { + usb_serial_open, /* -> open entry point */ + usb_serial_close, /* -> close entry point */ + usb_serial_free, /* -> free cookie */ + usb_serial_control, /* -> control entry point */ + usb_serial_read, /* -> read entry point */ + usb_serial_write, /* -> write entry point */ +#if defined(B_BEOS_VERSION_DANO) || defined(__HAIKU__) + usb_serial_select, /* -> select entry point */ + usb_serial_deselect /* -> deselect entry point */ +#endif + }; + + TRACE_FUNCALLS("> find_device(%s)\n", name); + return &deviceHooks; +} diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/Driver.h b/src/add-ons/kernel/drivers/ports/usb_serial/Driver.h new file mode 100644 index 0000000000..74bba9eb8b --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/Driver.h @@ -0,0 +1,103 @@ +/* + * 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_DRIVER_H_ +#define _USB_SERIAL_DRIVER_H_ + +#include +#include +#include + +#include "BeOSCompatibility.h" +#include "kernel_cpp.h" +#include "Tracing.h" +#include "USB3.h" + +extern "C" { +#include +} + +#define DRIVER_NAME "usb_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 usb_serial_line_coding_s { + uint32 speed; + uint8 stopbits; + uint8 parity; + uint8 databits; +} usb_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 usb_module_info *gUSBModule; +extern tty_module_info *gTTYModule; +extern struct ddomain gSerialDomain; + +extern "C" { +status_t usb_serial_device_added(usb_device device, void **cookie); +status_t usb_serial_device_removed(void *cookie); + +status_t init_hardware(); +void uninit_driver(); + +bool usb_serial_service(struct tty *ptty, struct ddrover *ddr, uint flags); + +status_t usb_serial_open(const char *name, uint32 flags, void **cookie); +status_t usb_serial_read(void *cookie, off_t position, void *buffer, size_t *numBytes); +status_t usb_serial_write(void *cookie, off_t position, const void *buffer, size_t *numBytes); +status_t usb_serial_control(void *cookie, uint32 op, void *arg, size_t length); +status_t usb_serial_select(void *cookie, uint8 event, uint32 ref, selectsync *sync); +status_t usb_serial_deselect(void *coookie, uint8 event, selectsync *sync); +status_t usb_serial_close(void *cookie); +status_t usb_serial_free(void *cookie); + +const char **publish_devices(); +device_hooks *find_device(const char *name); +} + +#endif //_USB_SERIAL_DRIVER_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/FTDI.cpp b/src/add-ons/kernel/drivers/ports/usb_serial/FTDI.cpp new file mode 100644 index 0000000000..78a0030cae --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/FTDI.cpp @@ -0,0 +1,227 @@ +/* + * 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 "FTDI.h" +#include "FTDIRegs.h" + +FTDIDevice::FTDIDevice(usb_device device, uint16 vendorID, uint16 productID, + const char *description) + : SerialDevice(device, vendorID, productID, description), + fHeaderLength(0), + fStatusMSR(0), + fStatusLSR(0) +{ +} + + +status_t +FTDIDevice::AddDevice(const usb_configuration_info *config) +{ + TRACE_FUNCALLS("> FTDIDevice::AddDevice(%08x, %08x)\n", this, config); + status_t status = ENODEV; + if (config->interface_count > 0) { + int32 pipesSet = 0; + usb_interface_info *interface = config->interface[0].active; + for (size_t i = 0; i < interface->endpoint_count; i++) { + usb_endpoint_info *endpoint = &interface->endpoint[i]; + if (endpoint->descr->attributes == USB_EP_ATTR_BULK) { + if (endpoint->descr->endpoint_address & USB_EP_ADDR_DIR_IN) { + SetReadPipe(endpoint->handle); + if (++pipesSet >= 3) + break; + } else { + if (endpoint->descr->endpoint_address) { + SetControlPipe(endpoint->handle); + SetWritePipe(endpoint->handle); + pipesSet += 2; + if (pipesSet >= 3) + break; + } + } + } + } + + if (pipesSet >= 3) { + if (ProductID() == PRODUCT_FTDI_8U100AX) + fHeaderLength = 1; + else + fHeaderLength = 0; + + status = B_OK; + } + } + + TRACE_FUNCRET("< FTDIDevice::AddDevice() returns: 0x%08x\n", status); + return status; +} + + +status_t +FTDIDevice::ResetDevice() +{ + TRACE_FUNCALLS("> FTDIDevice::ResetDevice(0x%08x)\n", this); + + size_t length = 0; + status_t status = gUSBModule->send_request(Device(), + USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, + FTDI_SIO_RESET, FTDI_SIO_RESET_SIO, + FTDI_PIT_DEFAULT, 0, NULL, &length); + + TRACE_FUNCRET("< FTDIDevice::ResetDevice() returns:%08x\n", status); + return status; +} + + +status_t +FTDIDevice::SetLineCoding(usb_serial_line_coding *lineCoding) +{ + TRACE_FUNCALLS("> FTDIDevice::SetLineCoding(0x%08x, {%d, 0x%02x, 0x%02x, 0x%02x})\n", + this, lineCoding->speed, lineCoding->stopbits, lineCoding->parity, + lineCoding->databits); + + int32 rate = 0; + if (ProductID() == PRODUCT_FTDI_8U100AX) { + switch (lineCoding->speed) { + case 300: rate = ftdi_sio_b300; break; + case 600: rate = ftdi_sio_b600; break; + case 1200: rate = ftdi_sio_b1200; break; + case 2400: rate = ftdi_sio_b2400; break; + case 4800: rate = ftdi_sio_b4800; break; + case 9600: rate = ftdi_sio_b9600; break; + case 19200: rate = ftdi_sio_b19200; break; + case 38400: rate = ftdi_sio_b38400; break; + case 57600: rate = ftdi_sio_b57600; break; + case 115200: rate = ftdi_sio_b115200; break; + default: + rate = ftdi_sio_b19200; + TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Datarate: %d is " + "not supported by this hardware. Defaulted to %d\n", + lineCoding->speed, rate); + break; + } + } else { + switch (lineCoding->speed) { + case 300: rate = ftdi_8u232am_b300; break; + case 600: rate = ftdi_8u232am_b600; break; + case 1200: rate = ftdi_8u232am_b1200; break; + case 2400: rate = ftdi_8u232am_b2400; break; + case 4800: rate = ftdi_8u232am_b4800; break; + case 9600: rate = ftdi_8u232am_b9600; break; + case 19200: rate = ftdi_8u232am_b19200; break; + case 38400: rate = ftdi_8u232am_b38400; break; + case 57600: rate = ftdi_8u232am_b57600; break; + case 115200: rate = ftdi_8u232am_b115200; break; + case 230400: rate = ftdi_8u232am_b230400; break; + case 460800: rate = ftdi_8u232am_b460800; break; + case 921600: rate = ftdi_8u232am_b921600; break; + default: + rate = ftdi_sio_b19200; + TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Datarate: %d is " + "not supported by this hardware. Defaulted to %d\n", + lineCoding->speed, rate); + break; + } + } + + size_t length = 0; + status_t status = gUSBModule->send_request(Device(), + USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, + FTDI_SIO_SET_BAUD_RATE, rate, + FTDI_PIT_DEFAULT, 0, NULL, &length); + if (status != B_OK) + TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): datarate set request failed: 0x%08x\n", status); + + int32 data = 0; + switch (lineCoding->stopbits) { + case LC_STOP_BIT_2: data = FTDI_SIO_SET_DATA_STOP_BITS_2; break; + case LC_STOP_BIT_1: data = FTDI_SIO_SET_DATA_STOP_BITS_1; break; + default: + TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Wrong stopbits param: %d\n", + lineCoding->stopbits); + break; + } + + switch (lineCoding->parity) { + case LC_PARITY_NONE: data |= FTDI_SIO_SET_DATA_PARITY_NONE; break; + case LC_PARITY_EVEN: data |= FTDI_SIO_SET_DATA_PARITY_EVEN; break; + case LC_PARITY_ODD: data |= FTDI_SIO_SET_DATA_PARITY_ODD; break; + default: + TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Wrong parity param: %d\n", + lineCoding->parity); + break; + } + + switch (lineCoding->databits) { + case 8: data |= FTDI_SIO_SET_DATA_BITS(8); break; + case 7: data |= FTDI_SIO_SET_DATA_BITS(7); break; + default: + TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Wrong databits param: %d\n", + lineCoding->databits); + break; + } + + length = 0; + status = gUSBModule->send_request(Device(), + USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, + FTDI_SIO_SET_DATA, data, + FTDI_PIT_DEFAULT, 0, NULL, &length); + if (status != B_OK) + TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): data set request failed: %08x\n", status); + + TRACE_FUNCRET("< FTDIDevice::SetLineCoding() returns: 0x%08x\n", status); + return status; +} + + +status_t +FTDIDevice::SetControlLineState(uint16 state) +{ + TRACE_FUNCALLS("> FTDIDevice::SetControlLineState(0x%08x, 0x%04x)\n", this, state); + + int32 control; + control = (state & CLS_LINE_RTS) ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW; + control |= (state & CLS_LINE_DTR) ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW; + + size_t length = 0; + status_t status = gUSBModule->send_request(Device(), + USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, + FTDI_SIO_MODEM_CTRL, control, + FTDI_PIT_DEFAULT, 0, NULL, &length); + + if (status != B_OK) + TRACE_ALWAYS("= FTDIDevice::SetControlLineState(): control set request failed: 0x%08x\n", status); + + TRACE_FUNCRET("< FTDIDevice::SetControlLineState() returns: 0x%08x\n", status); + return status; +} + + +void +FTDIDevice::OnRead(char **buffer, size_t *numBytes) +{ + fStatusMSR = FTDI_GET_MSR(*buffer); + fStatusLSR = FTDI_GET_LSR(*buffer); + TRACE("FTDIDevice::OnRead(): MSR: 0x%02x LSR: 0x%02x\n", fStatusMSR, fStatusLSR); + *buffer += 2; + *numBytes -= 2; +} + + +void +FTDIDevice::OnWrite(const char *buffer, size_t *numBytes) +{ + char *writeBuffer = WriteBuffer(); + if (fHeaderLength > 0) { + if (*numBytes >= WriteBufferSize() - fHeaderLength) + *numBytes = WriteBufferSize() - fHeaderLength; + + *writeBuffer = FTDI_OUT_TAG(*numBytes, FTDI_PIT_DEFAULT); + } + + memcpy(writeBuffer + fHeaderLength, buffer, *numBytes); + *numBytes += fHeaderLength; +} diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/FTDI.h b/src/add-ons/kernel/drivers/ports/usb_serial/FTDI.h new file mode 100644 index 0000000000..b065499d3f --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/FTDI.h @@ -0,0 +1,42 @@ +/* + * 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_FTDI_H_ +#define _USB_FTDI_H_ + +#include "SerialDevice.h" + +/* supported vendor and product ids */ +#define VENDOR_FTDI 0x0403 +#define PRODUCT_FTDI_8U100AX 0x8372 +#define PRODUCT_FTDI_8U232AM 0x6001 + +#define FTDI_BUFFER_SIZE 64 + + +class FTDIDevice : public SerialDevice { +public: + FTDIDevice(usb_device device, uint16 vendorID, + uint16 productID, const char *description); + +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); + +private: + size_t fHeaderLength; + uint8 fStatusMSR; + uint8 fStatusLSR; +}; + +#endif //_USB_FTDI_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/uftdireg.h b/src/add-ons/kernel/drivers/ports/usb_serial/FTDIRegs.h similarity index 81% rename from src/add-ons/kernel/drivers/ports/usb_serial/uftdireg.h rename to src/add-ons/kernel/drivers/ports/usb_serial/FTDIRegs.h index 04586e8030..2ae840130f 100644 --- a/src/add-ons/kernel/drivers/ports/usb_serial/uftdireg.h +++ b/src/add-ons/kernel/drivers/ports/usb_serial/FTDIRegs.h @@ -19,7 +19,7 @@ /* * Added to BeOS USB Serial Driver project by Siarzhuk Zharski - * + * * $Source: /cvsroot/sis4be/usb_serial/uftdireg.h,v $ * $Author: zharik $ * $Revision: 1.1 $ @@ -28,17 +28,17 @@ */ /* Vendor Request Interface */ -#define FTDI_SIO_RESET 0 /* Reset the port */ -#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ +#define FTDI_SIO_RESET 0 /* Reset the port */ +#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ #define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */ #define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */ -#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */ -#define FTDI_SIO_GET_STATUS 5 /* Retrieve current value of status reg */ +#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */ +#define FTDI_SIO_GET_STATUS 5 /* Retrieve current value of status reg */ #define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */ #define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */ /* Port Identifier Table */ -#define FTDI_PIT_DEFAULT 0 /* SIOA */ +#define FTDI_PIT_DEFAULT 0 /* SIOA */ #define FTDI_PIT_SIOA 1 /* SIOA */ #define FTDI_PIT_SIOB 2 /* SIOB */ #define FTDI_PIT_PARALLEL 3 /* Parallel */ @@ -74,9 +74,9 @@ enum uftdi_type { * */ /* FTDI_SIO_RESET */ -#define FTDI_SIO_RESET_SIO 0 -#define FTDI_SIO_RESET_PURGE_RX 1 -#define FTDI_SIO_RESET_PURGE_TX 2 +#define FTDI_SIO_RESET_SIO 0 +#define FTDI_SIO_RESET_PURGE_RX 1 +#define FTDI_SIO_RESET_PURGE_TX 2 /* @@ -142,16 +142,16 @@ enum { * */ /* FTDI_SIO_SET_DATA */ -#define FTDI_SIO_SET_DATA_BITS(n) (n) -#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8) -#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8) -#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8) -#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8) -#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8) -#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) -#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) -#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) -#define FTDI_SIO_SET_BREAK (0x1 << 14) +#define FTDI_SIO_SET_DATA_BITS(n) (n) +#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8) +#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8) +#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8) +#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8) +#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8) +#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) +#define FTDI_SIO_SET_BREAK (0x1 << 14) /* @@ -183,12 +183,12 @@ enum { * B10..15 Reserved */ /* FTDI_SIO_MODEM_CTRL */ -#define FTDI_SIO_SET_DTR_MASK 0x1 -#define FTDI_SIO_SET_DTR_HIGH (1 | ( FTDI_SIO_SET_DTR_MASK << 8)) -#define FTDI_SIO_SET_DTR_LOW (0 | ( FTDI_SIO_SET_DTR_MASK << 8)) -#define FTDI_SIO_SET_RTS_MASK 0x2 -#define FTDI_SIO_SET_RTS_HIGH (2 | ( FTDI_SIO_SET_RTS_MASK << 8)) -#define FTDI_SIO_SET_RTS_LOW (0 | ( FTDI_SIO_SET_RTS_MASK << 8)) +#define FTDI_SIO_SET_DTR_MASK 0x1 +#define FTDI_SIO_SET_DTR_HIGH (1 | ( FTDI_SIO_SET_DTR_MASK << 8)) +#define FTDI_SIO_SET_DTR_LOW (0 | ( FTDI_SIO_SET_DTR_MASK << 8)) +#define FTDI_SIO_SET_RTS_MASK 0x2 +#define FTDI_SIO_SET_RTS_HIGH (2 | ( FTDI_SIO_SET_RTS_MASK << 8)) +#define FTDI_SIO_SET_RTS_LOW (0 | ( FTDI_SIO_SET_RTS_MASK << 8)) /* @@ -216,10 +216,10 @@ enum { * XOFF character and the lValue field contains the XON character. */ /* FTDI_SIO_SET_FLOW_CTRL */ -#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 -#define FTDI_SIO_RTS_CTS_HS 0x1 -#define FTDI_SIO_DTR_DSR_HS 0x2 -#define FTDI_SIO_XON_XOFF_HS 0x4 +#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 +#define FTDI_SIO_RTS_CTS_HS 0x1 +#define FTDI_SIO_DTR_DSR_HS 0x2 +#define FTDI_SIO_XON_XOFF_HS 0x4 /* @@ -295,10 +295,10 @@ enum { * FTDI_SIO_GET_MODEM_STATUS * Retrieve the current value of the modem status register. */ -#define FTDI_SIO_CTS_MASK 0x10 -#define FTDI_SIO_DSR_MASK 0x20 -#define FTDI_SIO_RI_MASK 0x40 -#define FTDI_SIO_RLSD_MASK 0x80 +#define FTDI_SIO_CTS_MASK 0x10 +#define FTDI_SIO_DSR_MASK 0x20 +#define FTDI_SIO_RI_MASK 0x40 +#define FTDI_SIO_RLSD_MASK 0x80 @@ -350,9 +350,9 @@ enum { * B2..7 Length of message - (not including Byte 0) * */ -#define FTDI_PORT_MASK 0x0f -#define FTDI_MSR_MASK 0xf0 -#define FTDI_GET_MSR(p) (((p)[0]) & FTDI_MSR_MASK) -#define FTDI_GET_LSR(p) ((p)[1]) -#define FTDI_LSR_MASK (~0x60) /* interesting bits */ -#define FTDI_OUT_TAG(len, port) (((len) << 2) | (port)) +#define FTDI_PORT_MASK 0x0f +#define FTDI_MSR_MASK 0xf0 +#define FTDI_GET_MSR(p) (((p)[0]) & FTDI_MSR_MASK) +#define FTDI_GET_LSR(p) ((p)[1]) +#define FTDI_LSR_MASK (~0x60) /* interesting bits */ +#define FTDI_OUT_TAG(len, port) (((len) << 2) | (port)) diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/Jamfile b/src/add-ons/kernel/drivers/ports/usb_serial/Jamfile index b16073ef82..df9e696168 100644 --- a/src/add-ons/kernel/drivers/ports/usb_serial/Jamfile +++ b/src/add-ons/kernel/drivers/ports/usb_serial/Jamfile @@ -2,17 +2,17 @@ SubDir HAIKU_TOP src add-ons kernel drivers ports usb_serial ; SetSubDirSupportedPlatformsBeOSCompatible ; -local defines = [ FDefines B_USB_USE_V2_MODULE ] ; - -SubDirCcFlags $(defines) ; +SubDirC++Flags -fno-rtti ; KernelAddon usb_serial : - driver.c - tracing.c - acm.c - prolific.c - ftdi.c - klsi.c + Driver.cpp + SerialDevice.cpp + Tracing.cpp + + ACM.cpp + FTDI.cpp + KLSI.cpp + Prolific.cpp ; AddResources usb_serial : usb_serial.rdef ; diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/KLSI.cpp b/src/add-ons/kernel/drivers/ports/usb_serial/KLSI.cpp new file mode 100644 index 0000000000..423e6b8491 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/KLSI.cpp @@ -0,0 +1,161 @@ +/* + * 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 "KLSI.h" +#include + +KLSIDevice::KLSIDevice(usb_device device, uint16 vendorID, uint16 productID, + const char *description) + : SerialDevice(device, vendorID, productID, description) +{ +} + + +status_t +KLSIDevice::AddDevice(const usb_configuration_info *config) +{ + TRACE_FUNCALLS("> KLSIDevice::AddDevice(%08x, %08x)\n", this, config); + + int32 pipesSet = 0; + status_t status = ENODEV; + if (config->interface_count > 0) { + usb_interface_info *interface = config->interface[0].active; + for (size_t i = 0; i < interface->endpoint_count; i++) { + usb_endpoint_info *endpoint = &interface->endpoint[i]; + if (endpoint->descr->attributes == USB_EP_ATTR_INTERRUPT) { + if (endpoint->descr->endpoint_address & USB_EP_ADDR_DIR_IN) { + SetControlPipe(endpoint->handle); + if (++pipesSet >= 3) + break; + } + } else if (endpoint->descr->attributes == USB_EP_ATTR_BULK) { + if (endpoint->descr->endpoint_address & USB_EP_ADDR_DIR_IN) { + SetReadPipe(endpoint->handle); + if (++pipesSet >= 3) + break; + } else { + SetWritePipe(endpoint->handle); + if (++pipesSet >= 3) + break; + } + } + } + } + + if (pipesSet >= 3) + status = B_OK; + + TRACE_FUNCRET("< KLSIDevice::AddDevice() returns: 0x%08x\n", status); + return status; +} + + +status_t +KLSIDevice::ResetDevice() +{ + TRACE_FUNCALLS("> KLSIDevice::ResetDevice(%08x)\n", this); + + size_t length = 0; + status_t status = gUSBModule->send_request(Device(), + USB_REQTYPE_VENDOR | USB_REQTYPE_INTERFACE_OUT, + KLSI_CONF_REQUEST, + KLSI_CONF_REQUEST_READ_ON, 0, 0, NULL, &length); + + TRACE_FUNCRET("< KLSIDevice::ResetDevice() returns: 0x%08x\n", status); + return status; +} + + +status_t +KLSIDevice::SetLineCoding(usb_serial_line_coding *lineCoding) +{ + TRACE_FUNCALLS("> KLSIDevice::SetLineCoding(0x%08x, {%d, 0x%02x, 0x%02x, 0x%02x})\n", + this, lineCoding->speed, lineCoding->stopbits, lineCoding->parity, + lineCoding->databits); + + uint8 rate; + switch (lineCoding->speed) { + case 300: rate = klsi_sio_b300; break; + case 600: rate = klsi_sio_b600; break; + case 1200: rate = klsi_sio_b1200; break; + case 2400: rate = klsi_sio_b2400; break; + case 4800: rate = klsi_sio_b4800; break; + case 9600: rate = klsi_sio_b9600; break; + case 19200: rate = klsi_sio_b19200; break; + case 38400: rate = klsi_sio_b38400; break; + case 57600: rate = klsi_sio_b57600; break; + case 115200: rate = klsi_sio_b115200; break; + default: + rate = klsi_sio_b19200; + TRACE_ALWAYS("= KLSIDevice::SetLineCoding(): Datarate: %d is not " + "supported by this hardware. Defaulted to %d\n", + lineCoding->speed, rate); + break; + } + + uint8 codingPacket[5]; + codingPacket[0] = 5; /* size */ + codingPacket[1] = rate; + codingPacket[2] = lineCoding->databits; /* only 7,8 */ + codingPacket[3] = 0; /* unknown */ + codingPacket[4] = 1; /* unknown */ + + size_t length = 0; + status_t status = gUSBModule->send_request(Device(), + USB_REQTYPE_VENDOR | USB_REQTYPE_INTERFACE_OUT, + KLSI_SET_REQUEST, 0, 0, + sizeof(codingPacket), codingPacket, &length); + + if (status != B_OK) + TRACE_ALWAYS("= KLSIDevice::SetLineCoding(): datarate set request failed: 0x%08x\n", status); + + TRACE_FUNCRET("< KLSIDevice::SetLineCoding() returns: 0x%08x\n", status); + return status; +} + + +void +KLSIDevice::OnRead(char **buffer, size_t *numBytes) +{ + if (*numBytes <= 2) { + *numBytes = 0; + return; + } + + size_t bytes = B_LENDIAN_TO_HOST_INT16(*(uint16 *)(*buffer)); + *numBytes = MIN(bytes, *numBytes - 2); + *buffer += 2; +} + + +void +KLSIDevice::OnWrite(const char *buffer, size_t *numBytes) +{ + if (*numBytes >= WriteBufferSize() - 2) + *numBytes = WriteBufferSize() - 2; + + char *writeBuffer = WriteBuffer(); + *((uint16 *)writeBuffer) = B_HOST_TO_LENDIAN_INT16(*numBytes); + memcpy(writeBuffer + 2, buffer, *numBytes); + *numBytes += 2; +} + + +void +KLSIDevice::OnClose() +{ + TRACE_FUNCALLS("> KLSIDevice::OnClose(%08x)\n", this); + + size_t length = 0; + status_t status = gUSBModule->send_request(Device(), + USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, + KLSI_CONF_REQUEST, + KLSI_CONF_REQUEST_READ_OFF, 0, 0, + NULL, &length); + + TRACE_FUNCRET("< KLSIDevice::OnClose() returns: 0x%08x\n", status); +} diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/KLSI.h b/src/add-ons/kernel/drivers/ports/usb_serial/KLSI.h new file mode 100644 index 0000000000..c9265cc7fa --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/KLSI.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2007-2008 by Michael Lotz + * Heavily based on the original usb_serial driver which is: + * + * Copyright (c) 2003-2004 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + */ +#ifndef _USB_KLSI_H_ +#define _USB_KLSI_H_ + +#include "SerialDevice.h" + +/* supported vendor and product ids */ +#define VENDOR_PALM 0x0830 +#define VENDOR_KLSI 0x05e9 +#define PRODUCT_PALM_CONNECT 0x0080 +#define PRODUCT_KLSI_KL5KUSB105D 0x00c0 + +/* protocol defines */ +#define KLSI_SET_REQUEST 0x01 +#define KLSI_POLL_REQUEST 0x02 +#define KLSI_CONF_REQUEST 0x03 +#define KLSI_CONF_REQUEST_READ_ON 0x03 +#define KLSI_CONF_REQUEST_READ_OFF 0x02 + +// not sure +#define KLSI_BUFFER_SIZE 64 + +enum { + klsi_sio_b115200 = 0, + klsi_sio_b57600 = 1, + klsi_sio_b38400 = 2, + klsi_sio_b19200 = 4, + klsi_sio_b9600 = 6, + /* unchecked */ + klsi_sio_b4800 = 8, + klsi_sio_b2400 = 9, + klsi_sio_b1200 = 10, + klsi_sio_b600 = 11, + klsi_sio_b300 = 12 +}; + + +class KLSIDevice : public SerialDevice { +public: + KLSIDevice(usb_device device, uint16 vendorID, + uint16 productID, const char *description); + +virtual status_t AddDevice(const usb_configuration_info *config); + +virtual status_t ResetDevice(); + +virtual status_t SetLineCoding(usb_serial_line_coding *coding); + +virtual void OnRead(char **buffer, size_t *numBytes); +virtual void OnWrite(const char *buffer, size_t *numBytes); +virtual void OnClose(); +}; + +#endif //_USB_KLSI_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/Prolific.cpp b/src/add-ons/kernel/drivers/ports/usb_serial/Prolific.cpp new file mode 100644 index 0000000000..aae76e86cc --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/Prolific.cpp @@ -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. + */ +#include "Prolific.h" + +ProlificDevice::ProlificDevice(usb_device device, uint16 vendorID, + uint16 productID, const char *description) + : ACMDevice(device, vendorID, productID, description), + fIsHX(false) +{ +} + + +status_t +ProlificDevice::AddDevice(const usb_configuration_info *config) +{ + TRACE_FUNCALLS("> ProlificDevice::AddDevice(%08x, %08x)\n", this, config); + + // check for device type. + // Linux checks for type 0, 1 and HX, but handles 0 and 1 the same. + // We'll just check for HX then. + const usb_device_descriptor *deviceDescriptor = NULL; + deviceDescriptor = gUSBModule->get_device_descriptor(Device()); + if (deviceDescriptor) { + fIsHX = (deviceDescriptor->device_class != 0x02 + && deviceDescriptor->max_packet_size_0 == 0x40); + } + + int32 pipesSet = 0; + status_t status = ENODEV; + if (config->interface_count > 0) { + usb_interface_info *interface = config->interface[0].active; + for (size_t i = 0; i < interface->endpoint_count; i++) { + usb_endpoint_info *endpoint = &interface->endpoint[i]; + if (endpoint->descr->attributes == USB_EP_ATTR_INTERRUPT) { + if (endpoint->descr->endpoint_address & USB_EP_ADDR_DIR_IN) { + SetControlPipe(endpoint->handle); + pipesSet++; + } + } + } + + /* They say that USB-RSAQ1 has 2 interfaces */ + if (config->interface_count >= 2) + interface = config->interface[1].active; + + for (size_t i = 0; i < interface->endpoint_count; i++) { + usb_endpoint_info *endpoint = &interface->endpoint[i]; + if (endpoint->descr->attributes == USB_EP_ATTR_BULK) { + if (endpoint->descr->endpoint_address & USB_EP_ADDR_DIR_IN) { + SetReadPipe(endpoint->handle); + if (++pipesSet >= 3) + break; + } else { + SetWritePipe(endpoint->handle); + if (++pipesSet >= 3) + break; + } + } + } + + if (pipesSet >= 3) + status = B_OK; + } + + TRACE_FUNCRET("< ProlificDevice::AddDevice() returns: 0x%08x\n", status); + return status; +} + + +struct request_item { + bool out; + uint16 value; + uint16 index; +}; + +/* Linux sends all those, and it seems to work */ +/* see drivers/usb/serial/pl2303.c */ +static struct request_item prolific_reset_common[] = { + { false, 0x8484, 0 }, + { true, 0x0404, 0 }, + { false, 0x8484, 0 }, + { false, 0x8383, 0 }, + { false, 0x8484, 0 }, + { true, 0x0404, 1 }, + { false, 0x8484, 0 }, + { false, 0x8383, 0 }, + { true, 0x0000, 1 }, + { true, 0x0001, 0 } +}; + +static struct request_item prolific_reset_common_hx[] = { + { true, 2, 0x44 }, + { true, 8, 0 }, + { true, 0, 0 } +}; + +static struct request_item prolific_reset_common_nhx[] = { + { true, 2, 0x24 } +}; + + +status_t +ProlificDevice::SendRequestList(request_item *list, size_t length) +{ + for (size_t i = 0; i < length; i++) { + char buffer[10]; + size_t bufferLength = 1; + status_t status = gUSBModule->send_request(Device(), + USB_REQTYPE_VENDOR | (list[i].out ? USB_REQTYPE_DEVICE_OUT : USB_REQTYPE_DEVICE_IN), + PROLIFIC_SET_REQUEST, + list[i].value, + list[i].index, + list[i].out ? 0 : bufferLength, + list[i].out ? NULL : buffer, + &bufferLength); + TRACE(" ProlificDevice::SendRequestList(): request[%d]: 0x%08lx\n", i, status); + } + + return B_OK; +} + + +status_t +ProlificDevice::ResetDevice() +{ + TRACE_FUNCALLS("> ProlificDevice::ResetDevice(%08x)\n", this); + + SendRequestList(prolific_reset_common, SIZEOF(prolific_reset_common)); + if (fIsHX) + SendRequestList(prolific_reset_common_hx, SIZEOF(prolific_reset_common_hx)); + else + SendRequestList(prolific_reset_common_nhx, SIZEOF(prolific_reset_common_nhx)); + + status_t status = B_OK; /* discard */ + TRACE_FUNCRET("< ProlificDevice::ResetDevice() returns: 0x%08x\n", status); + return status; +} diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/Prolific.h b/src/add-ons/kernel/drivers/ports/usb_serial/Prolific.h new file mode 100644 index 0000000000..81e6de0843 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/Prolific.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007-2008 by Michael Lotz + * Heavily based on the original usb_serial driver which is: + * + * Copyright (c) 2003-2004 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + */ +#ifndef _USB_PROLIFIC_H_ +#define _USB_PROLIFIC_H_ + +#include "ACM.h" + +/* supported vendor and product ids */ +#define VENDOR_PROLIFIC 0x067b +#define VENDOR_IODATA 0x04bb +#define VENDOR_ATEN 0x0557 +#define VENDOR_TDK 0x04bf +#define VENDOR_RATOC 0x0584 +#define VENDOR_ELECOM 0x056e +#define VENDOR_SOURCENEXT 0x0833 +#define VENDOR_HAL 0x0b41 + +#define PRODUCT_IODATA_USBRSAQ 0x0a03 +#define PRODUCT_PROLIFIC_RSAQ2 0x04bb +#define PRODUCT_ATEN_UC232A 0x2008 +#define PRODUCT_PROLIFIC_PL2303 0x2303 +#define PRODUCT_TDK_UHA6400 0x0117 +#define PRODUCT_RATOC_REXUSB60 0xb000 +#define PRODUCT_ELECOM_UCSGT 0x5003 +#define PRODUCT_SOURCENEXT_KEIKAI8 0x039f +#define PRODUCT_SOURCENEXT_KEIKAI8_CHG 0x012e +#define PRODUCT_HAL_IMR001 0x0011 + +/* protocol defines */ +#define PROLIFIC_SET_REQUEST 0x01 + +#define PROLIFIC_BUF_SIZE 256 + +struct request_item; + + +class ProlificDevice : public ACMDevice { +public: + ProlificDevice(usb_device device, + uint16 vendorID, uint16 productID, + const char *description); + +virtual status_t AddDevice(const usb_configuration_info *config); + +virtual status_t ResetDevice(); + +private: + status_t SendRequestList(request_item *list, size_t length); + + bool fIsHX; +}; + +#endif //_USB_PROLIFIC_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp b/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp new file mode 100644 index 0000000000..419ed885eb --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp @@ -0,0 +1,662 @@ +/* + * 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), + fControlPipe(0), + fReadPipe(0), + fWritePipe(0), + fBufferArea(-1), + fReadBuffer(NULL), + fReadBufferSize(0), + fWriteBuffer(NULL), + fWriteBufferSize(0), + fInterruptBuffer(NULL), + fInterruptBufferSize(0), + fDoneRead(-1), + fDoneWrite(-1), + fControlOut(0), + fInputStopped(false), + fDeviceThread(-1), + fStopDeviceThread(false) +{ + memset(&fTTYFile, 0, sizeof(ttyfile)); + memset(&fTTY, 0, sizeof(tty)); +} + + +SerialDevice::~SerialDevice() +{ + fStopDeviceThread = true; + gUSBModule->cancel_queued_transfers(fReadPipe); + gUSBModule->cancel_queued_transfers(fWritePipe); + gUSBModule->cancel_queued_transfers(fControlPipe); + + if (fDoneRead >= B_OK) + delete_sem(fDoneRead); + if (fDoneWrite >= B_OK) + delete_sem(fDoneWrite); + + int32 result = B_OK; + wait_for_thread(fDeviceThread, &result); + + if (fBufferArea >= B_OK) + delete_area(fBufferArea); + + benaphore_destroy(&fReadLock); + benaphore_destroy(&fWriteLock); +} + + +status_t +SerialDevice::Init() +{ + fDoneRead = create_sem(0, "usb_serial:done_read"); + fDoneWrite = create_sem(0, "usb_serial:done_write"); + benaphore_init(&fReadLock, "usb_serial:read_lock"); + benaphore_init(&fWriteLock, "usb_serial:write_lock"); + + fReadBufferSize = fWriteBufferSize = ROUNDUP(DEF_BUFFER_SIZE, 16); + fInterruptBufferSize = 16; + + 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) +{ + 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"); + return status; +} + + +status_t +SerialDevice::Read(char *buffer, size_t *numBytes) +{ + struct ddrover *ddr = gTTYModule->ddrstart(NULL); + if (!ddr) { + *numBytes = 0; + return B_NO_MEMORY; + } + + status_t status = benaphore_lock(&fReadLock); + if (status != B_OK) { + TRACE_ALWAYS("read: failed to get read lock\n"); + *numBytes = 0; + return status; + } + + status = gTTYModule->ttyread(&fTTYFile, ddr, buffer, numBytes); + gTTYModule->ddrdone(ddr); + + benaphore_unlock(&fReadLock); + return status; +} + + +status_t +SerialDevice::Write(const char *buffer, size_t *numBytes) +{ + size_t bytesLeft = *numBytes; + *numBytes = 0; + + status_t status = benaphore_lock(&fWriteLock); + if (status != B_OK) { + TRACE_ALWAYS("write: failed to get write lock\n"); + return status; + } + + while (bytesLeft > 0) { + size_t length = MIN(bytesLeft, fWriteBufferSize); + OnWrite(buffer, &length); + + status = gUSBModule->queue_bulk(fWritePipe, fWriteBuffer, + length, 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 += fActualLengthWrite; + *numBytes += fActualLengthWrite; + bytesLeft -= fActualLengthWrite; + } + + benaphore_unlock(&fWriteLock); + return status; +} + + +status_t +SerialDevice::Control(uint32 op, void *arg, size_t length) +{ + 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) +{ + 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) +{ + 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(); + + 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); + 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; +} + + +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) +{ + // 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) { + 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/usb_serial/SerialDevice.h b/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.h new file mode 100644 index 0000000000..ce8f923039 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.h @@ -0,0 +1,131 @@ +/* + * 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_DEVICE_H_ +#define _USB_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(); + + /* 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); +virtual void OnClose(); + +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 + + /* 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 */ + benaphore fReadLock; + benaphore fWriteLock; +}; + +#endif // _USB_DEVICE_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/Tracing.cpp b/src/add-ons/kernel/drivers/ports/usb_serial/Tracing.cpp new file mode 100644 index 0000000000..c3c8e78364 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/Tracing.cpp @@ -0,0 +1,188 @@ +/* + * 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" + +extern "C" { +#include +} + +#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/usb_serial/Tracing.h b/src/add-ons/kernel/drivers/ports/usb_serial/Tracing.h new file mode 100644 index 0000000000..65af5c5525 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_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/usb_serial/USB3.h b/src/add-ons/kernel/drivers/ports/usb_serial/USB3.h new file mode 100644 index 0000000000..7e0d196c15 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/USB3.h @@ -0,0 +1,227 @@ +/* + * Version 3 USB Device Driver API + * + * Copyright 2006, Haiku Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef _USB_V3_H_ +#define _USB_V3_H_ + +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct usb_module_info usb_module_info; + +typedef uint32 usb_id; +typedef usb_id usb_device; +typedef usb_id usb_interface; +typedef usb_id usb_pipe; + +typedef struct usb_endpoint_info usb_endpoint_info; +typedef struct usb_interface_info usb_interface_info; +typedef struct usb_interface_list usb_interface_list; +typedef struct usb_configuration_info usb_configuration_info; + +typedef struct usb_notify_hooks { + status_t (*device_added)(usb_device device, void **cookie); + status_t (*device_removed)(void *cookie); +} usb_notify_hooks; + +typedef struct usb_support_descriptor { + uint8 dev_class; + uint8 dev_subclass; + uint8 dev_protocol; + uint16 vendor; + uint16 product; +} usb_support_descriptor; + +struct usb_endpoint_info { + usb_endpoint_descriptor *descr; /* descriptor and handle */ + usb_pipe handle; /* of this endpoint/pipe */ +}; + +struct usb_interface_info { + usb_interface_descriptor *descr; /* descriptor and handle */ + usb_interface handle; /* of this interface */ + + size_t endpoint_count; /* count and list of endpoints */ + usb_endpoint_info *endpoint; /* in this interface */ + + size_t generic_count; /* unparsed descriptors in */ + usb_descriptor **generic; /* this interface */ +}; + +struct usb_interface_list { + size_t alt_count; /* count and list of alternate */ + usb_interface_info *alt; /* interfaces available */ + + usb_interface_info *active; /* currently active alternate */ +}; + +struct usb_configuration_info { + usb_configuration_descriptor *descr; /* descriptor of this config */ + + size_t interface_count;/* interfaces in this config */ + usb_interface_list *interface; +}; + +typedef struct { + int16 request_length; + int16 actual_length; + status_t status; +} usb_iso_packet_descriptor; + +// Flags for queue_isochronous +#define USB_ISO_ASAP 0x01 + +typedef void (*usb_callback_func)(void *cookie, status_t status, void *data, + size_t actualLength); + + +/* The usb_module_info represents the public API of the USB Stack. */ +struct usb_module_info { + bus_manager_info binfo; + + /* + * Use register_driver() to inform the Stack of your interest to support + * USB devices. Support descriptors are used to indicate support for a + * specific device class/subclass/protocol or vendor/product. + * A value of 0 can be used as a wildcard for all fields. + * + * Would you like to be notified about all added hubs (class 0x09) you + * would use a support descriptor like this for register_driver: + * usb_support_descriptor hub_devs = { 9, 0, 0, 0, 0 }; + * + * If you intend to support just any device, or you at least want to be + * notified about any device, just pass NULL as the supportDescriptor and + * 0 as the supportDescriptorCount to register_driver. + */ + status_t (*register_driver)(const char *driverName, + const usb_support_descriptor *supportDescriptors, + size_t supportDescriptorCount, + const char *optionalRepublishDriverName); + + /* + * Install notification hooks using your registered driverName. The + * device_added hook will be called for every device that matches the + * support descriptors you provided in register_driver. + * When first installing the hooks you will receive a notification about + * any already present matching device. If you return B_OK in this hook, + * you can use the id that is provided. If the hook indicates an error, + * the resources will be deallocated and you may not use the usb_device + * that is provided. In this case you will not receive a device_removed + * notification for the device either. + */ + status_t (*install_notify)(const char *driverName, + const usb_notify_hooks *hooks); + status_t (*uninstall_notify)(const char *driverName); + + /* Get the device descriptor of a device. */ + const usb_device_descriptor *(*get_device_descriptor)(usb_device device); + + /* Get the nth supported configuration of a device*/ + const usb_configuration_info *(*get_nth_configuration)(usb_device device, + uint index); + + /* Get the current configuration */ + const usb_configuration_info *(*get_configuration)(usb_device device); + + /* Set the current configuration */ + status_t (*set_configuration)(usb_device device, + const usb_configuration_info *configuration); + + status_t (*set_alt_interface)(usb_device device, + const usb_interface_info *interface); + + /* + * Standard device requests - convenience functions + * The provided handle may be a usb_device, usb_pipe or usb_interface + */ + status_t (*set_feature)(usb_id handle, uint16 selector); + status_t (*clear_feature)(usb_id handle, uint16 selector); + status_t (*get_status)(usb_id handle, uint16 *status); + + status_t (*get_descriptor)(usb_device device, + uint8 descriptorType, uint8 index, + uint16 languageID, void *data, + size_t dataLength, + size_t *actualLength); + + /* Generic device request function - synchronous */ + status_t (*send_request)(usb_device device, + uint8 requestType, uint8 request, + uint16 value, uint16 index, + uint16 length, void *data, + size_t *actualLength); + + /* + * Asynchronous request queueing. These functions return immediately + * and the return code only tells whether the _queuing_ of the request + * was successful or not. It doesn't indicate transfer success or error. + * + * When the transfer is finished, the provided callback function is + * called with the transfer status, a pointer to the data buffer and + * the actually transfered length as well as with the callbackCookie + * that was used when queuing the request. + */ + status_t (*queue_interrupt)(usb_pipe pipe, + void *data, size_t dataLength, + usb_callback_func callback, + void *callbackCookie); + + status_t (*queue_bulk)(usb_pipe pipe, + void *data, size_t dataLength, + usb_callback_func callback, + void *callbackCookie); + + status_t (*queue_bulk_v)(usb_pipe pipe, + iovec *vector, size_t vectorCount, + usb_callback_func callback, + void *callbackCookie); + + status_t (*queue_isochronous)(usb_pipe pipe, + void *data, size_t dataLength, + usb_iso_packet_descriptor *packetDesc, + uint32 packetCount, + uint32 *startingFrameNumber, + uint32 flags, + usb_callback_func callback, + void *callbackCookie); + + status_t (*queue_request)(usb_device device, + uint8 requestType, uint8 request, + uint16 value, uint16 index, + uint16 length, void *data, + usb_callback_func callback, + void *callbackCookie); + + status_t (*set_pipe_policy)(usb_pipe pipe, + uint8 maxNumQueuedPackets, + uint16 maxBufferDurationMS, + uint16 sampleSize); + + /* Cancel all pending async requests in a pipe */ + status_t (*cancel_queued_transfers)(usb_pipe pipe); + + /* tuning, timeouts, etc */ + status_t (*usb_ioctl)(uint32 opcode, void *buffer, + size_t bufferSize); +}; + + +#define B_USB_MODULE_NAME "bus_managers/usb/v3" + + +#ifdef __cplusplus +} +#endif + +#endif /* !_USB_V3_H_ */ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/acm.c b/src/add-ons/kernel/drivers/ports/usb_serial/acm.c deleted file mode 100644 index 0b2ed7432e..0000000000 --- a/src/add-ons/kernel/drivers/ports/usb_serial/acm.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2003 by Siarzhuk Zharski - * Distributed under the terms of the MIT License. - * - */ - -#include -#include -#include -#include - -#include "driver.h" -#include "acm.h" - -status_t add_acm_device(usb_serial_device *usd, - const usb_configuration_info *uci) -{ - struct usb_endpoint_info *comm_epi = NULL; - struct usb_endpoint_info *data_out_epi = NULL; - struct usb_endpoint_info *data_in_epi = NULL; - status_t status = ENODEV; - int i = 0; - - TRACE_FUNCALLS("> add_acm_device(%08x, %08x)\n", usd, uci); - - for(i=0; i < uci->interface_count; i++){ - usb_interface_descriptor *uid = - uci->interface[i].active->descr; - if(uid->interface_class == USB_INT_CLASS_CDC && - uid->interface_subclass == USB_INT_SUBCLASS_ABSTRACT_CONTROL_MODEL && - uid->num_endpoints == 1){ - comm_epi = uci->interface[i].active->endpoint; - } - - if(uid->interface_class == USB_INT_CLASS_CDC_DATA && - (uid->interface_subclass == 2 || // ????????????? - uid->interface_subclass == USB_INT_SUBCLASS_DATA)){ - if(uid->num_endpoints == 2){ - data_out_epi = &uci->interface[i].active->endpoint[0]; - data_in_epi = &uci->interface[i].active->endpoint[1]; - } - } - if(comm_epi && data_out_epi && data_in_epi) - break; - } - - if(comm_epi && data_out_epi && data_in_epi){ - status = add_device(usd, uci, comm_epi, data_out_epi, data_in_epi); - } - - TRACE_FUNCRET("< add_acm_device returns:%08x\n", status); - return status; -} - -status_t reset_acm_device(usb_serial_device *usd){ - status_t status = B_OK; - TRACE_FUNCALLS("> reset_acm_device(%08x)\n", usd); - TRACE_FUNCRET("< reset_acm_device returns:%08x\n", status); - return status; -} - -status_t set_line_coding_acm(usb_serial_device *usd, - usb_serial_line_coding *line_coding){ - size_t len = 0; - status_t status = B_OK; - TRACE_FUNCALLS("> set_line_coding_acm(%08x, {%d, %02x, %02x, %02x})\n", - usd, line_coding->speed, - line_coding->stopbits, - line_coding->parity, - line_coding->databits); - status = (*usb_m->send_request)(usd->dev, - USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, - SET_LINE_CODING, 0x0, 0x0, - sizeof(usb_serial_line_coding), - line_coding, - sizeof(usb_serial_line_coding), &len); - TRACE_FUNCRET("< set_line_coding_acm returns:%08x\n", status); - return status; -} - -status_t set_control_line_state_acm(usb_serial_device *usd, uint16 state){ - size_t len = 0; - status_t status = B_OK; - TRACE_FUNCALLS("> set_control_line_state_acm(%08x, %04x)\n", usd, state); - status = (*usb_m->send_request)(usd->dev, - USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, - SET_CONTROL_LINE_STATE, state, 0, 0, 0, 0, - &len); - TRACE_FUNCRET("< set_control_line_state_acm returns:%08x\n", status); - return status; -} - -void on_read_acm(usb_serial_device *usd, char **buf, size_t *num_bytes){ -} - -void on_write_acm(usb_serial_device *usd, const char *buf, size_t *num_bytes){ - if(*num_bytes > usd->write_buffer_size) - *num_bytes = usd->write_buffer_size; - memcpy(usd->write_buffer, buf, *num_bytes); -} - -void on_close_acm(usb_serial_device *usd){ - TRACE_FUNCALLS("> add_acm_device(%08x)\n", usd); - (*usb_m->cancel_queued_transfers)(usd->pipe_read); - (*usb_m->cancel_queued_transfers)(usd->pipe_write); - (*usb_m->cancel_queued_transfers)(usd->pipe_control); -} - diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/acm.h b/src/add-ons/kernel/drivers/ports/usb_serial/acm.h deleted file mode 100644 index e1043cdd6c..0000000000 --- a/src/add-ons/kernel/drivers/ports/usb_serial/acm.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2003 by Siarzhuk Zharski - * Distributed under the terms of the MIT License. - * - */ - -#ifndef _USB_ACM_H_ - #define _USB_ACM_H_ - -status_t add_acm_device(usb_serial_device *usd, - const usb_configuration_info *uci); -status_t reset_acm_device(usb_serial_device *usd); -status_t set_line_coding_acm(usb_serial_device *usd, - usb_serial_line_coding *line_coding); -status_t set_control_line_state_acm(usb_serial_device *usd, uint16 state); -void on_read_acm(usb_serial_device *usd, char **buf, size_t *num_bytes); -void on_write_acm(usb_serial_device *usd, const char *buf, size_t *num_bytes); -void on_close_acm(usb_serial_device *usd); - -#endif //_USB_ACM_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/driver.c b/src/add-ons/kernel/drivers/ports/usb_serial/driver.c deleted file mode 100644 index f21e82db45..0000000000 --- a/src/add-ons/kernel/drivers/ports/usb_serial/driver.c +++ /dev/null @@ -1,945 +0,0 @@ -/* - * Copyright (c) 2003 by Siarzhuk Zharski - * Distributed under the terms of the MIT License. - * - */ - -#include -#include -#include -#include -#include -#include /* strerror */ -#include /* strtol */ -#include /* sprintf */ - -#include "driver.h" -#include "acm.h" -#include "prolific.h" -#include "ftdi.h" -#include "klsi.h" - -/* driver callbacks forward declarations */ -static status_t usb_serial_open (const char *name, uint32 flags, void** cookie); -static status_t usb_serial_read (void* cookie, - off_t position, void *buf, size_t* num_bytes); -static status_t usb_serial_write (void* cookie, off_t position, - const void* buffer, size_t* num_bytes); -static status_t usb_serial_select (void* cookie, uint8 event, uint32 ref, selectsync *_sync); -static status_t usb_serial_deselect (void* cookie, uint8 event, selectsync *_sync); -static status_t usb_serial_control (void* cookie, uint32 op, void* arg, size_t len); -static status_t usb_serial_close (void* cookie); -static status_t usb_serial_free (void* cookie); -/* USB notify callbacks forward declarations */ -status_t usb_serial_device_added(const usb_device *dev, void **cookie); -status_t usb_serial_device_removed(void *cookie); - -/* The base name of drivers created in /dev/ports/ directory */ -#define BASENAME_LEN 0x09 /*must be synchronized with below !!!*/ -static const char *basename = "ports/usb%u"; - -/* function pointers for the device hooks entry points */ -device_hooks usb_serial_hooks = { - usb_serial_open, /* -> open entry point */ - usb_serial_close, /* -> close entry point */ - usb_serial_free, /* -> free cookie */ - usb_serial_control, /* -> control entry point */ - usb_serial_read, /* -> read entry point */ - usb_serial_write, /* -> write entry point */ -#if defined(B_BEOS_VERSION_DANO) || defined(__HAIKU__) - usb_serial_select, /* -> select entry point */ - usb_serial_deselect /* -> deselect entry point */ -#endif - /* readv / read_pages ??? */ - /* writev */ -}; -/* USB notify hooks */ -static usb_notify_hooks notify_hooks = { - &usb_serial_device_added, - &usb_serial_device_removed -}; -/* kernel modules */ -usb_module_info *usb_m; /* usb layer */ -tty_module_info *tty_m; /* tty layer */ - -struct tty usb_serial_tty[DEVICES_COUNT]; -struct ddomain usb_serial_dd; -/* hardware devices, supported by this driver. - See description field for human readable names */ -usb_serial_hw usb_serial_hw_devices[] = { - {0, 0, add_acm_device, reset_acm_device, - set_line_coding_acm, set_control_line_state_acm, - on_read_acm, on_write_acm, on_close_acm, - "CDC ACM compatible device"}, - - {VND_PROLIFIC, PROD_PROLIFIC_RSAQ2, - add_prolific_device, reset_prolific_device, - set_line_coding_acm, set_control_line_state_acm, - on_read_acm, on_write_acm, on_close_acm, - "PL2303 Serial adapter (IODATA USB-RSAQ2)"}, - {VND_IODATA, PROD_IODATA_USBRSAQ, - add_prolific_device, reset_prolific_device, - set_line_coding_acm, set_control_line_state_acm, - on_read_acm, on_write_acm, on_close_acm, - "I/O Data USB serial adapter USB-RSAQ1"}, - {VND_ATEN, PROD_ATEN_UC232A, - add_prolific_device, reset_prolific_device, - set_line_coding_acm, set_control_line_state_acm, - on_read_acm, on_write_acm, on_close_acm, - "Aten Serial adapter"}, - {VND_TDK, PROD_TDK_UHA6400, - add_prolific_device, reset_prolific_device, - set_line_coding_acm, set_control_line_state_acm, - on_read_acm, on_write_acm, on_close_acm, - "TDK USB-PHS Adapter UHA6400"}, - {VND_RATOC, PROD_RATOC_REXUSB60, - add_prolific_device, reset_prolific_device, - set_line_coding_acm, set_control_line_state_acm, - on_read_acm, on_write_acm, on_close_acm, - "Ratoc USB serial adapter REX-USB60"}, - {VND_PROLIFIC, PROD_PROLIFIC_PL2303, - add_prolific_device, reset_prolific_device, - set_line_coding_acm, set_control_line_state_acm, - on_read_acm, on_write_acm, on_close_acm, - "PL2303 Serial adapter (ATEN/IOGEAR UC232A)"}, - {VND_ELECOM, PROD_ELECOM_UCSGT, - add_prolific_device, reset_prolific_device, - set_line_coding_acm, set_control_line_state_acm, - on_read_acm, on_write_acm, on_close_acm, - "Elecom UC-SGT"}, - {VND_SOURCENEXT, PROD_SOURCENEXT_KEIKAI8, - add_prolific_device, reset_prolific_device, - set_line_coding_acm, set_control_line_state_acm, - on_read_acm, on_write_acm, on_close_acm, - "SOURCENEXT KeikaiDenwa 8"}, - {VND_SOURCENEXT, PROD_SOURCENEXT_KEIKAI8_CHG, - add_prolific_device, reset_prolific_device, - set_line_coding_acm, set_control_line_state_acm, - on_read_acm, on_write_acm, on_close_acm, - "SOURCENEXT KeikaiDenwa 8 with charger"}, - {VND_HAL, PROD_HAL_IMR001, - add_prolific_device, reset_prolific_device, - set_line_coding_acm, set_control_line_state_acm, - on_read_acm, on_write_acm, on_close_acm, - "HAL Corporation Crossam2+USB"}, - - {VND_FTDI, PROD_8U100AX, - add_ftdi_device, reset_ftdi_device, - set_line_coding_ftdi, set_control_line_state_ftdi, - on_read_ftdi, on_write_ftdi, on_close_ftdi, - "FTDI 8U100AX serial converter"}, - {VND_FTDI, PROD_8U232AM, - add_ftdi_device, reset_ftdi_device, - set_line_coding_ftdi, set_control_line_state_ftdi, - on_read_ftdi, on_write_ftdi, on_close_ftdi, - "FTDI 8U232AM serial converter"}, - - {VND_PALM, PROD_PALM_CONNECT, - add_klsi_device, reset_klsi_device, - set_line_coding_klsi, set_control_line_state_klsi, - on_read_klsi, on_write_klsi, on_close_klsi, - "PalmConnect RS232"}, - {VND_KLSI, PROD_KLSI_KL5KUSB105D, - add_klsi_device, reset_klsi_device, - set_line_coding_klsi, set_control_line_state_klsi, - on_read_klsi, on_write_klsi, on_close_klsi, - "KLSI KL5KUSB105D"}, - -}; -/* supported devices*/ -usb_support_descriptor *supported_devices; -/* main devices table locking semaphore */ -sem_id usb_serial_lock = -1; -/* array of pointers to device objects */ -usb_serial_device *usb_serial_devices[DEVICES_COUNT]; -/* the names of "ports" */ -char * usb_serial_names[DEVICES_COUNT + 1]; -/* speed constants, supported by this driver. */ -const uint32 serial_tty_speed[] = { - 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 -}; - -/* init_hardware - called once the first time the driver is loaded */ -status_t init_hardware (void){ - TRACE("init_hardware\n"); /*special case - no file-logging activated now*/ - return B_OK; -} - -/* init_driver - optional function - called every time the driver - is loaded. */ -status_t init_driver (void){ - int i; - status_t status = B_OK; - load_setting(); - create_log(); - - TRACE_FUNCALLS("init_driver\n"); - - if((status = get_module(B_TTY_MODULE_NAME, (module_info **)&tty_m)) == B_OK){ - if((status = get_module(B_USB_MODULE_NAME, (module_info **)&usb_m)) == B_OK){ - if(tty_m && usb_m){ - for(i = 0; i < DEVICES_COUNT; i++) - usb_serial_devices[i] = 0; - - usb_serial_names[0] = NULL; - load_driver_symbols(DRIVER_NAME); - - /* XXX: needs more error checking! */ - - // build the list of usb supported devices from our own hw list, - // so it's always up to date. - supported_devices = malloc(sizeof(usb_support_descriptor) * SIZEOF(usb_serial_hw_devices)); - // ACM devices - supported_devices[0].dev_class = USB_DEV_CLASS_COMM; - supported_devices[0].dev_subclass = 0; - supported_devices[0].dev_protocol = 0; - supported_devices[0].vendor = 0; - supported_devices[0].product = 0; - // other devices - for (i = 1; i < SIZEOF(usb_serial_hw_devices); i++){ - supported_devices[i].dev_class = 0; - supported_devices[i].dev_subclass = 0; - supported_devices[i].dev_protocol = 0; - supported_devices[i].vendor = usb_serial_hw_devices[i].vendor_id; - supported_devices[i].product = usb_serial_hw_devices[i].product_id; - } - - (*usb_m->register_driver)(DRIVER_NAME, supported_devices, - SIZEOF(usb_serial_hw_devices), DRIVER_NAME); - (*usb_m->install_notify)(DRIVER_NAME, ¬ify_hooks); - - usb_serial_lock = create_sem(1, DRIVER_NAME"_devices_table_lock"); - }else{ - status = B_ERROR; - TRACE_ALWAYS("init_driver failed: tty_m:%08x usb_m:%08x", tty_m, usb_m); - } - if (status != B_OK) - put_module(B_USB_MODULE_NAME); - }else - TRACE_ALWAYS("init_driver failed:%lx cannot get a module %s", status, - B_USB_MODULE_NAME); - if (status != B_OK) - put_module(B_TTY_MODULE_NAME); - }else - TRACE_ALWAYS("init_driver failed:%lx cannot get a module %s", status, - B_TTY_MODULE_NAME); - - TRACE_FUNCRET("init_driver returns:%08x\n", status); - return status; -} - -/* uninit_driver - optional function - called every time the driver - is unloaded */ -void uninit_driver (void){ - int i; - TRACE_FUNCALLS("uninit_driver\n"); - - (*usb_m->uninstall_notify)(DRIVER_NAME); - free(supported_devices); - acquire_sem(usb_serial_lock); - - for(i = 0; i < DEVICES_COUNT; i++) - if(usb_serial_devices[i]){ - delete_area(usb_serial_devices[i]->buffers_area); - delete_sem(usb_serial_devices[i]->done_read); - delete_sem(usb_serial_devices[i]->done_write); - free(usb_serial_devices[i]); - usb_serial_devices[i] = 0; - } - - release_sem_etc(usb_serial_lock, 1, B_DO_NOT_RESCHEDULE); - delete_sem(usb_serial_lock); - - for(i = 0; usb_serial_names[i]; i++) - free(usb_serial_names[i]); - - put_module(B_USB_MODULE_NAME); - put_module(B_TTY_MODULE_NAME); -} - -void usb_serial_device_notify_in(void *cookie, - uint32 status, void *data, uint32 actual_len){ - TRACE_FUNCALLS("usb_serial_device_notify_in:cookie:%08x status:%08x data:%08x len:%d\n", cookie, status, data, actual_len); - if(cookie){ - usb_serial_device *usd = ((usb_serial_device_info *)cookie)->device; - usd->actual_len_read = actual_len; - usd->dev_status_read = status; - release_sem(usd->done_read); - } -} - -void usb_serial_device_notify_out(void *cookie, uint32 status, - void *data, uint32 actual_len){ - TRACE_FUNCALLS("usb_serial_device_notify_out:cookie:%08x status:%08x " - "data:%08x len:%d\n", cookie, status, data, actual_len); - if(cookie){ - usb_serial_device *usd = ((usb_serial_device_info *)cookie)->device; - usd->actual_len_write = actual_len; - usd->dev_status_write = status; - release_sem(usd->done_write); - } -} - -status_t usb_serial_device_thread(void *param){ - status_t status = B_ERROR; - usb_serial_device_info *usdi = (usb_serial_device_info *)param; - usb_serial_device *usd = usdi->device; - TRACE_FUNCALLS("usb_serial_device_thread:%08x\n", param); - - while(true){ - size_t i, to_read; - char *buf; - struct ddrover *ddr; - usd->actual_len_read = 0; - usd->dev_status_read = 0; - status = (*usb_m->queue_bulk)(usd->pipe_read, usd->read_buffer, - usd->read_buffer_size, usb_serial_device_notify_in, usdi); - if(status != B_OK){ - TRACE_ALWAYS("usb_serial_device_thread : queue_bulk error : %lx\n", status); - break; - } - - status = acquire_sem_etc(usd->done_read, 1, B_CAN_INTERRUPT, 0); - if(status != B_OK){ - TRACE_ALWAYS("usb_serial_device_thread : acquire_sem_etc : " - "error %08lx (%s)\n", status, strerror(status)); - break; - } - - if(usd->dev_status_read){ - TRACE_ALWAYS("usb_serial_device_thread : dev_status error !!!\n"); - break; - } - - buf = usd->read_buffer; - to_read = usd->actual_len_read; - (*usd->hw->on_read)(usd, &buf, &to_read); - - if(!to_read) - continue; - - ddr = (*tty_m->ddrstart)(NULL); - if(!ddr){ - TRACE_ALWAYS("usb_serial_device_thread : ddrstart problem !!!\n"); - status = B_NO_MEMORY; - break; - } - - (*tty_m->ttyilock)(usd->tty, ddr, true); - for(i = 0; i < to_read; i++){ - (*tty_m->ttyin)(usd->tty, ddr, buf[i]); - } - (*tty_m->ttyilock)(usd->tty, ddr, false); - (*tty_m->ddrdone)(ddr); - } - - TRACE_FUNCRET("usb_serial_device_thread returns %08x\n", status); - return status; -} - -void usb_serial_setmodes(usb_serial_device *usd){ - usb_serial_line_coding line_coding; - struct termios tios; - - int newctrl, baud_index; - TRACE_FUNCALLS("usb_serial_setmodes:%08x\n", usd); - - memcpy(&tios, &usd->tty->t, sizeof(struct termios)); - newctrl = usd->ctrlout; - - TRACE_FUNCRES(trace_termios, &tios); - TRACE("newctrl:%08x\n", newctrl); - - baud_index = tios.c_cflag & CBAUD; - if(baud_index > SIZEOF(serial_tty_speed)) - baud_index = SIZEOF(serial_tty_speed) - 1; - - line_coding.speed = serial_tty_speed[baud_index]; - line_coding.stopbits = ( tios.c_cflag & CSTOPB ) ? LC_STOP_BIT_2 : LC_STOP_BIT_1; - - if(PARENB & tios.c_cflag){ - line_coding.parity = LC_PARITY_EVEN; - - if(PARODD & tios.c_cflag){ - line_coding.parity = LC_PARITY_ODD; - } - }else - line_coding.parity = LC_PARITY_NONE; - - line_coding.databits = (tios.c_cflag & CS8) ? 8 : 7; - - if(line_coding.speed == 0){ - newctrl &= 0xfffffffe; - line_coding.speed = usd->line_coding.speed; - }else - newctrl = CLS_LINE_DTR; - - if(usd->ctrlout != newctrl ){ - usd->ctrlout = newctrl; - TRACE("newctrl send to modem:%08x\n", newctrl); - (*usd->hw->set_control_line_state)(usd, newctrl); - } - - if(memcmp (&line_coding, &usd->line_coding, sizeof(usb_serial_line_coding))){ - usd->line_coding.speed = line_coding.speed; - usd->line_coding.stopbits = line_coding.stopbits; - usd->line_coding.databits = line_coding.databits; - usd->line_coding.parity = line_coding.parity; - TRACE("send to modem:speed %d sb:%08x db:%08x parity:%08x\n", - usd->line_coding.speed, usd->line_coding.stopbits, - usd->line_coding.databits, usd->line_coding.parity); - (*usd->hw->set_line_coding)(usd, &usd->line_coding); - } -} - -bool usb_serial_service(struct tty *ptty, struct ddrover *ddr, uint flags){ - int i; - bool bret = false; - usb_serial_device *usd; - TRACE_FUNCALLS("usb_serial_service:%08x ddr:%08x flags:%08x\n", ptty, ddr, flags); - - for(i = 0; i < DEVICES_COUNT; i++){ - if(usb_serial_devices[i]){ - if(ptty == usb_serial_devices[i]->tty){ - usd = usb_serial_devices[i]; - break; - } - } - } - - if(usd){ - if(flags <= TTYGETSIGNALS){ - switch(flags){ - case TTYENABLE: - (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWDCD, false); - (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWCTS, true); - - usd->ctrlout = CLS_LINE_DTR | CLS_LINE_RTS; - (*usd->hw->set_control_line_state)(usd, usd->ctrlout); - break; - - case TTYDISABLE: - - (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWDCD, false); - - usd->ctrlout = 0x0; - (*usd->hw->set_control_line_state)(usd, usd->ctrlout); - break; - - case TTYISTOP: - (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWCTS, false); - break; - - case TTYIRESUME: - (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWCTS, true); - break; - - case TTYGETSIGNALS: - (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWDCD, true); - (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWCTS, true); - (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWDSR, false); - (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWRI, false); - break; - - case TTYSETMODES: - usb_serial_setmodes(usd); - break; - - case TTYOSTART: - case TTYOSYNC: - case TTYSETBREAK: - case TTYCLRBREAK: - case TTYSETDTR: - case TTYCLRDTR: - break; - } - } - bret = true; - } - - TRACE_FUNCRET("usb_serial_service returns %d\n", bret); - return bret; -} - -void usb_serial_notify_interrupt(void *cookie, uint32 status, - void *data, uint32 actual_len){ - TRACE_FUNCALLS("usb_serial_notify_interrupt : %p %lx %p %ld\n", - cookie, status, data, actual_len); - if(cookie){ - usb_serial_device *usd = ((usb_serial_device_info *)cookie)->device; - usd->actual_len_interrupt = actual_len; - usd->dev_status_interrupt = status; - } -} - -/* usb_serial_open - handle open() calls */ -static status_t usb_serial_open (const char *name, uint32 flags, void** cookie){ - int i; - status_t status = ENODEV; - TRACE_FUNCALLS("usb_serial_open:%s flags:%d cookie:%08x\n", - name, flags, cookie); - - for(i=0;i= 0 && i < DEVICES_COUNT){ - acquire_sem(usb_serial_lock); - if(usb_serial_devices[i]){ - usb_serial_device_info *usdi = malloc(sizeof(usb_serial_device_info)); - if(usdi){ - struct ddrover *ddr; - memset(usdi, 0, sizeof(usb_serial_device_info)); - *cookie = usdi; - - TRACE("cookie in open:%08x\n", *cookie); - - usdi->device = usb_serial_devices[i]; - - (*tty_m->ttyinit)(&usb_serial_tty[i], true); - - usdi->ttyfile.tty = &usb_serial_tty[i]; - usdi->ttyfile.flags = flags; - usb_serial_devices[i]->tty = &usb_serial_tty[i]; - - (*usdi->device->hw->reset_device)(usdi->device); - - TRACE("Opened:%s %08x\n", usdi->device->hw->descr, usdi->device->dev); - - ddr = (*tty_m->ddrstart)(NULL); - if(ddr){ - (*tty_m->ddacquire)(ddr, &usb_serial_dd); - status = (*tty_m->ttyopen)(&usdi->ttyfile, ddr, usb_serial_service); - (*tty_m->ddrdone)(ddr); - - if(status == B_OK){ - sem_id sem = spawn_kernel_thread(usb_serial_device_thread, - "usb_serial_device_thread", 0xa, usdi); - if(sem != -1) - resume_thread(sem); - else - TRACE_ALWAYS("usb_serial_open: cannot spawn kernel thread!!!\n"); - - usdi->device->ctrlout = CLS_LINE_DTR | CLS_LINE_RTS; - (*usdi->device->hw->set_control_line_state)(usdi->device, - usdi->device->ctrlout); - - status = (*usb_m->queue_interrupt)(usdi->device->pipe_control, - usdi->device->interrupt_buffer, - usdi->device->interrupt_buffer_size, - usb_serial_notify_interrupt, usdi); - } - }else - status = B_NO_MEMORY; - - if(status != B_OK) - free(usdi); - }else - status = B_NO_MEMORY; - } - release_sem(usb_serial_lock); - } - - TRACE_FUNCRET("usb_serial_open returns:%08x\n", status); - return status; -} - -/* usb_serial_read - handle read() calls */ -static status_t usb_serial_read (void* cookie, off_t position, - void *buf, size_t* num_bytes){ - status_t status = B_OK; - struct ddrover *ddr; - TRACE_FUNCALLS("usb_serial_read:%08x position:%Ld buf:%08x len:%d\n", - cookie, position, buf, *num_bytes); - - ddr = (*tty_m->ddrstart)(NULL); - if(ddr){ - if(cookie) - status = (*tty_m->ttyread)(cookie, ddr, buf, num_bytes); - else - (*tty_m->ddacquire)(ddr, &usb_serial_dd); - (*tty_m->ddrdone)(ddr); - }else{ - TRACE_ALWAYS("usb_serial_read : ddrstart problem !!!\n"); - status = B_NO_MEMORY; - } - - TRACE_FUNCRET("usb_serial_read returns:%08x readed:%d\n", status, *num_bytes); - return status; -} - -/* usb_serial_write - handle write() calls */ - -static status_t usb_serial_write (void* cookie, off_t position, - const void* buffer, size_t* num_bytes){ - status_t status = B_OK; - usb_serial_device_info *usdi = (usb_serial_device_info *)cookie; - usb_serial_device *usd = usdi->device; - size_t to_write = *num_bytes; - TRACE_FUNCALLS("usb_serial_write:%08x position:%Ld buf:%08x len:%d\n", - cookie, position, buffer, *num_bytes); - *num_bytes = 0; /* tell caller nothing was written */ - - while(to_write > 0){ - size_t len = to_write; - - (*usd->hw->on_write)(usd, buffer, &len); - - usd->actual_len_write = 0; - usd->dev_status_write = 0; - - status = (*usb_m->queue_bulk)(usd->pipe_write, usd->write_buffer, - len, usb_serial_device_notify_out, cookie); - if(status != B_OK){ - TRACE_ALWAYS("usb_serial_write : dev %p status %lx", cookie, status); - break; - } - - status = acquire_sem_etc(usd->done_write, 1, B_CAN_INTERRUPT, 0); - if(status != B_OK){ - TRACE_ALWAYS("usb_serial_write : acquire_sem_etc() %lx (%s)", - status, strerror(status)); - break; - } - - ((const char*)buffer) += usd->actual_len_write; - *num_bytes += usd->actual_len_write; - to_write -= usd->actual_len_write; - } - - TRACE_FUNCRET("usb_serial_write returns:%08x written:%d\n", status, *num_bytes); - return status; -} - -/* usb_serial_control - handle ioctl calls */ -static status_t usb_serial_control (void* cookie, uint32 op, void* arg, size_t len){ - status_t status = B_BAD_VALUE; - TRACE_FUNCALLS("usb_serial_control cookie:%08x op:%08x arg:%08x len:%d\n", - cookie, op, arg, len); - - if(cookie){ - struct ddrover *ddr = (*tty_m->ddrstart)(NULL); - if(ddr){ - status = (*tty_m->ttycontrol)(cookie, ddr, op, arg, len); - (*tty_m->ddrdone)(ddr); - }else - status = B_NO_MEMORY; - }else - status = ENODEV; - - TRACE_FUNCRET("usb_serial_control returns:%08x\n", status); - return status; -} - -#if defined(B_BEOS_VERSION_DANO) || defined(__HAIKU__) - -/* usb_serial_select - handle select start */ -static status_t usb_serial_select (void* cookie, uint8 event, uint32 ref, selectsync *_sync){ - status_t status = B_BAD_VALUE; - TRACE_FUNCALLS("usb_serial_select cookie:%08x event:%08x ref:%08x sync:%p\n", - cookie, event, ref, _sync); - - if(cookie){ - struct ddrover *ddr = (*tty_m->ddrstart)(NULL); - if(ddr){ - status = (*tty_m->ttyselect)(cookie, ddr, event, ref, _sync); - (*tty_m->ddrdone)(ddr); - }else - status = B_NO_MEMORY; - }else - status = ENODEV; - - TRACE_FUNCRET("usb_serial_select returns:%08x\n", status); - return status; -} - -/* usb_serial_deselect - handle select exit */ -static status_t usb_serial_deselect (void* cookie, uint8 event, selectsync *_sync){ - status_t status = B_BAD_VALUE; - TRACE_FUNCALLS("usb_serial_deselect cookie:%08x event:%08x sync:%p\n", - cookie, event, _sync); - - if(cookie){ - struct ddrover *ddr = (*tty_m->ddrstart)(NULL); - if(ddr){ - status = (*tty_m->ttydeselect)(cookie, ddr, event, _sync); - (*tty_m->ddrdone)(ddr); - }else - status = B_NO_MEMORY; - }else - status = ENODEV; - - TRACE_FUNCRET("usb_serial_deselect returns:%08x\n", status); - return status; -} - -#endif - -/* usb_serial_close - handle close() calls */ -static status_t usb_serial_close (void* cookie){ - status_t status = ENODEV; - TRACE_FUNCALLS("usb_serial_close:%08x\n", cookie); - - if(cookie){ - usb_serial_device_info *usdi = (usb_serial_device_info *)cookie; - usb_serial_device *usd = usdi->device; - struct ddrover *ddr; - - (*usd->hw->on_close)(usd); - - ddr = (*tty_m->ddrstart)(NULL); - if(ddr){ - status = (*tty_m->ttyclose)(cookie, ddr); - (*tty_m->ddrdone)(ddr); - }else - status = B_NO_MEMORY; - } - - TRACE_FUNCRET("usb_serial_close returns:%08x\n", status); - return status; -} - -/* usb_serial_free - called after the last device is closed, and after - all i/o is complete.*/ -static status_t usb_serial_free (void* cookie){ - status_t status = B_OK; - TRACE_FUNCALLS("usb_serial_free:%08x\n", cookie); - - if(cookie){ - struct ddrover *ddr = (*tty_m->ddrstart)(NULL); - if(ddr){ - status = (*tty_m->ttyfree)(cookie, ddr); - (*tty_m->ddrdone)(ddr); - }else - status = B_NO_MEMORY; - free(cookie); - } - - TRACE_FUNCRET("usb_serial_free returns:%08x\n", status); - return status; -} - -/* publish_devices - return a null-terminated array of devices - supported by this driver. */ -const char** publish_devices(){ - int i, j; - TRACE_FUNCALLS("publish_devices\n"); - - for(i=0; usb_serial_names[i]; i++) - free(usb_serial_names[i]); - - acquire_sem(usb_serial_lock); - for(i=0, j=0; i < DEVICES_COUNT; i++){ - if(usb_serial_devices[i]){ - usb_serial_names[j] = malloc(strlen(basename + 2)); - if(usb_serial_names[j]){ - sprintf(usb_serial_names[j], basename, i); - j++; - } - else - TRACE_ALWAYS("publish_devices - NO MEMORY\n"); - } - } - usb_serial_names[j] = NULL; - release_sem(usb_serial_lock); - - return (const char **)&usb_serial_names[0]; -} - -/* find_device - return ptr to device hooks structure for a - given device name */ -device_hooks* find_device(const char* name){ - TRACE_FUNCALLS("find_device(%s)\n", name); - return &usb_serial_hooks; -} - -status_t add_device(usb_serial_device *usd, const usb_configuration_info *uci, - usb_endpoint_info *comm_epi, - usb_endpoint_info *data_out_epi, - usb_endpoint_info *data_in_epi){ - char name[32]; - status_t status = ENODEV; - size_t buf_len; - int i = 0; - - TRACE_FUNCALLS("add_device(%08x, %08x, %08x, %08x, %08x)\n", - usd, uci, comm_epi, data_in_epi, data_out_epi); - - acquire_sem(usb_serial_lock); - - for(i = 0; i < DEVICES_COUNT; i++){ - if(usb_serial_devices[i] != NULL) - continue; - - usb_serial_devices[i] = usd; - - usd->active = 1; - usd->open = 0; - - sprintf(name, "usb_serial:%d:done_read", i ); - usd->done_read = create_sem(0, name); - - sprintf(name, "usb_serial:%d:done_write", i); - usd->done_write = create_sem(0, name); - - usd->tty = NULL; - - buf_len = usd->read_buffer_size + usd->write_buffer_size + - usd->interrupt_buffer_size; - - usd->buffers_area = create_area("usb_serial:buffers_area", - (void *)&usd->read_buffer, - B_ANY_KERNEL_ADDRESS, - ROUNDUP(buf_len, B_PAGE_SIZE), - B_CONTIGUOUS, B_READ_AREA|B_WRITE_AREA); - - usd->write_buffer = usd->read_buffer + usd->read_buffer_size; - usd->interrupt_buffer = usd->write_buffer + usd->write_buffer_size; - - (*usb_m->set_configuration)(usd->dev, uci); - - usd->pipe_control = (comm_epi) ? comm_epi->handle : 0; - usd->pipe_write = data_out_epi->handle; - usd->pipe_read = data_in_epi->handle; - - status = B_OK; - break; - } - - release_sem(usb_serial_lock); - - TRACE_FUNCRET("add_device returns:%08x\n", status); - return status; -} - - -status_t usb_serial_device_added(const usb_device *dev, void **cookie){ - int i; - status_t status = B_OK; - const usb_device_descriptor *udd; - usb_serial_device *usd = 0; - TRACE_FUNCALLS("usb_serial_device_added:%08x cookie:%08x\n", dev, cookie); - - udd = (*usb_m->get_device_descriptor)(dev); - - TRACE_ALWAYS("Probing device: %08x/%08x\n", udd->vendor_id, udd->product_id); - - *cookie = 0; - for(i=1; i < sizeof(usb_serial_hw_devices)/sizeof(usb_serial_hw_devices[0]); i++) - if(usb_serial_hw_devices[i].vendor_id == udd->vendor_id - && usb_serial_hw_devices[i].product_id == udd->product_id){ - const usb_configuration_info *uci; - uci = (*usb_m->get_nth_configuration)(dev, 0); - if(uci){ - usd = malloc(sizeof(usb_serial_device)); - if(usd){ - usd->dev = dev; - usd->hw = &usb_serial_hw_devices[i]; - usd->read_buffer_size = - usd->write_buffer_size = - usd->interrupt_buffer_size = ROUNDUP(DEF_BUFFER_SIZE, 16); - if((status = (*usb_serial_hw_devices[i].add_device)(usd, uci)) == B_OK){ - *cookie = dev; - TRACE_ALWAYS("%s (%04x/%04x) added \n", - usb_serial_hw_devices[i].descr, - usb_serial_hw_devices[i].vendor_id, - usb_serial_hw_devices[i].product_id); - }else - free(usd); - }else - status = B_NO_MEMORY; - } - break; - } - - if(!*cookie){ - if(b_acm_support && - udd->device_class == USB_DEV_CLASS_COMM && - udd->device_subclass == 0 && - udd->device_protocol == 0 ){ - const usb_configuration_info *uci; - uint16 idx = 0; - do{ - uci = (*usb_m->get_nth_configuration)(dev, idx++); - if(uci){ - if(uci->interface_count != 2) - continue; - usd = malloc(sizeof(usb_serial_device)); - if(usd){ - usd->dev = dev; - usd->hw = &usb_serial_hw_devices[0]; - usd->read_buffer_size = - usd->write_buffer_size = - usd->interrupt_buffer_size = ROUNDUP(DEF_BUFFER_SIZE, 16); - if((status = (*usb_serial_hw_devices[0].add_device)(usd, uci)) == B_OK){ - *cookie = dev; - TRACE_ALWAYS("%s (%04x/%04x) added \n", - usb_serial_hw_devices[0].descr, - udd->vendor_id, udd->product_id); - }else - free(usd); - }else - status = B_NO_MEMORY; - } - }while(uci); - }else{ - TRACE_ALWAYS("device has wrong class, subclass and protocol\n"); - status = B_ERROR; - } - } - TRACE_FUNCRET("usb_serial_device_added returns:%08x\n", status); - return status; -} - -status_t usb_serial_device_removed(void *cookie){ - int i; - status_t status = B_OK; - usb_device *ud = (usb_device *) cookie; - TRACE_FUNCALLS("usb_serial_device_removed:%08x\n", cookie); - - acquire_sem(usb_serial_lock); - - for(i = 0; i < DEVICES_COUNT; i++ ){ - usb_serial_device *usd = usb_serial_devices[i]; - if(usd){ - if(ud == usd->dev){ - usd->active = 0; - if(!usd->open) - break; - - delete_area(usd->buffers_area); - delete_sem(usd->done_read); - delete_sem(usd->done_write); - free(usd); - usb_serial_devices[i] = 0; - } - } - } - - release_sem(usb_serial_lock); - - TRACE_FUNCRET("usb_serial_device_removed returns:%08x\n", status); - return status; -} - diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/driver.h b/src/add-ons/kernel/drivers/ports/usb_serial/driver.h deleted file mode 100644 index fef4b524ec..0000000000 --- a/src/add-ons/kernel/drivers/ports/usb_serial/driver.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2003 by Siarzhuk Zharski - * Distributed under the terms of the MIT License. - * - */ - -#ifndef _USB_SERIAL_DRIVER_H_ - #define _USB_SERIAL_DRIVER_H_ - -/* The name of this driver ... */ -#define DRIVER_NAME "usb_serial" -/* Maximal count of devices supported by this driver at the same time. */ -#define DEVICES_COUNT 20 - -#include "tracing.h" - -/* 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)) -/* buffer size */ -#define DEF_BUFFER_SIZE 0x100 - -/* 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 _s_usb_serial_line_coding{ - uint32 speed; - uint8 stopbits; - uint8 parity; - uint8 databits; -} usb_serial_line_coding; - -/* "forgotten" requests for CDC ACM devices */ -#define SET_LINE_CODING 0x20 -#define SET_CONTROL_LINE_STATE 0x22 - -/* control line states */ -#define CLS_LINE_DTR 0x0001 -#define CLS_LINE_RTS 0x0002 - -/* "forgotten" 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_ABSTRACT_CONTROL_MODEL 0x02 - -#define USB_INT_CLASS_CDC_DATA 0x0a -#define USB_INT_SUBCLASS_DATA 0x00 - -/* a kind of forward declaration */ -typedef struct _s_usb_serial_device usb_serial_device; - -/* usb_serial_hw - represents the different hardware devices */ -typedef struct _s_usb_serial_hw{ - uint16 vendor_id; /* vendor id and card id of device */ - uint16 product_id; - /* callbacks used in "customization" of the driver behaviour */ - status_t (*add_device)(usb_serial_device *usd, - const usb_configuration_info *uci); - status_t (*reset_device)(usb_serial_device *usd); - status_t (*set_line_coding)(usb_serial_device *usd, - usb_serial_line_coding *line_coding); - status_t (*set_control_line_state)(usb_serial_device *usd, uint16 state); - void (*on_read)(usb_serial_device *usd, char **buf, size_t *num_bytes); - void (*on_write)(usb_serial_device *usd, const char *buf, - size_t *num_bytes); - void (*on_close)(usb_serial_device *usd); - const char *descr; /* informational description */ -}usb_serial_hw; - -status_t add_device(usb_serial_device *usd, const usb_configuration_info *uci, - usb_endpoint_info *comm_epi, - usb_endpoint_info *data_out_epi, - usb_endpoint_info *data_in_epi); - -/* this one was typedefed into usb_serial_device - see above for details - this struct represents the main device object */ -struct _s_usb_serial_device{ - int active; /* is device active - performing some tasks */ - int32 open; /* is device opened */ - const usb_device *dev; /* points to usb device handle */ - /* communication pipes */ - usb_pipe *pipe_control; - usb_pipe *pipe_read; - usb_pipe *pipe_write; - /* line coding */ - usb_serial_line_coding line_coding; - - /* data buffers */ - area_id buffers_area; - /* read buffer */ - char *read_buffer; - size_t read_buffer_size; - /* write buffer */ - char *write_buffer; - size_t write_buffer_size; - /* interrupt buffer */ - char *interrupt_buffer; - size_t interrupt_buffer_size; - - /* variables used in callback functionality */ - size_t actual_len_read; - uint32 dev_status_read; - size_t actual_len_write; - uint32 dev_status_write; - size_t actual_len_interrupt; - uint32 dev_status_interrupt; - /* semaphores used in callbacks */ - sem_id done_read; - sem_id done_write; - - uint16 ctrlout; - - struct tty *tty; - - usb_serial_hw *hw; /* points to corresponding hardware description */ - /* place for device specific data */ - union{ - struct _spec_acm{ /* ACM-compatible devices */ - }acm; - struct _spec_prolific{ /* Prolific devices*/ - bool is_HX; /* Linux handles HX type differently */ - }prolific; - struct _spec_ftdi{ /* FTDI devices*/ - uint8 hdrlen; - uint8 status_msr; - uint8 status_lsr; - }ftdi; - struct _spec_klsi{ /* KLSI/PalmConnect */ - }klsi; - }spec; -}; /*already typedef-ed - see comment above! */ -/* high-level of abstraction of the device*/ -typedef struct _s_usb_serial_device_info{ - struct ttyfile ttyfile; /* */ - usb_serial_device *device; /* */ -}usb_serial_device_info; - -extern usb_serial_device *usb_serial_devices[]; -extern char * usb_serial_names[]; -extern usb_module_info *usb_m; - -#endif//_USB_SERIAL_DRIVER_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.c b/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.c deleted file mode 100644 index 7bcfc3deee..0000000000 --- a/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2003 by Siarzhuk Zharski - * Distributed under the terms of the MIT License. - * - */ - -#include -#include -#include -#include -#include - -#include "driver.h" -#include "ftdi.h" -#include "uftdireg.h" - - -status_t add_ftdi_device(usb_serial_device *usd, - const usb_configuration_info *uci) -{ - struct usb_endpoint_info *comm_epi = NULL; - struct usb_endpoint_info *data_out_epi = NULL; - struct usb_endpoint_info *data_in_epi = NULL; - status_t status = ENODEV; - int i = 0; - - TRACE_FUNCALLS("> add_ftdi_device(%08x, %08x)\n", usd, uci); - - if(uci->interface_count){ - struct usb_interface_info *uii = uci->interface[0].active; - for(i = 0; i < uii->endpoint_count; i++){ - if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_BULK){ - if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN) - == USB_EP_ADDR_DIR_IN){ - data_in_epi = &uii->endpoint[i]; - }else{ - if(uii->endpoint[i].descr->endpoint_address - /*USB_EP_ADDR_DIR_OUT = 0x0*/){ - comm_epi = data_out_epi = &uii->endpoint[i]; - } - } - } - } - - if(comm_epi && data_in_epi && data_out_epi){ - if(usd->hw->product_id == PROD_8U100AX) - usd->spec.ftdi.hdrlen = 1; - else - usd->spec.ftdi.hdrlen = 0; - - usd->read_buffer_size = - usd->write_buffer_size = - usd->interrupt_buffer_size = ROUNDUP(FTDI_BUF_SIZE, 16); - status = add_device(usd, uci, comm_epi, data_out_epi, data_in_epi); - } - } - - TRACE_FUNCRET("< add_ftdi_device returns:%08x\n", status); - return status; -} - -status_t reset_ftdi_device(usb_serial_device *usd){ - status_t status = B_OK; - size_t len = 0; - TRACE_FUNCALLS("> reset_ftdi_device(%08x)\n", usd); - status = (*usb_m->send_request)(usd->dev, - USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, - FTDI_SIO_RESET, FTDI_SIO_RESET_SIO, - FTDI_PIT_DEFAULT, 0, 0, 0, &len); - TRACE_FUNCRET("< reset_ftdi_device returns:%08x\n", status); - return status; -} - -status_t set_line_coding_ftdi(usb_serial_device *usd, - usb_serial_line_coding *line_coding){ - status_t status = B_OK; - int32 rate, data = 0; - size_t len1 = 0, len2 = 0; - TRACE_FUNCALLS("> set_line_coding_ftdi(%08x, {%d, %02x, %02x, %02x})\n", - usd, line_coding->speed, - line_coding->stopbits, - line_coding->parity, - line_coding->databits); - - if(usd->hw->product_id == PROD_8U100AX){ - switch (line_coding->speed){ - case 300: rate = ftdi_sio_b300; break; - case 600: rate = ftdi_sio_b600; break; - case 1200: rate = ftdi_sio_b1200; break; - case 2400: rate = ftdi_sio_b2400; break; - case 4800: rate = ftdi_sio_b4800; break; - case 9600: rate = ftdi_sio_b9600; break; - case 19200: rate = ftdi_sio_b19200; break; - case 38400: rate = ftdi_sio_b38400; break; - case 57600: rate = ftdi_sio_b57600; break; - case 115200: rate = ftdi_sio_b115200; break; - default: - rate = ftdi_sio_b19200; - TRACE_ALWAYS("= set_line_coding_ftdi: Datarate:%d is not supported " - "by this hardware. Defaulted to %d\n", - line_coding->speed, rate); - break; - } - }else{ - switch(line_coding->speed){ - case 300: rate = ftdi_8u232am_b300; break; - case 600: rate = ftdi_8u232am_b600; break; - case 1200: rate = ftdi_8u232am_b1200; break; - case 2400: rate = ftdi_8u232am_b2400; break; - case 4800: rate = ftdi_8u232am_b4800; break; - case 9600: rate = ftdi_8u232am_b9600; break; - case 19200: rate = ftdi_8u232am_b19200; break; - case 38400: rate = ftdi_8u232am_b38400; break; - case 57600: rate = ftdi_8u232am_b57600; break; - case 115200: rate = ftdi_8u232am_b115200; break; - case 230400: rate = ftdi_8u232am_b230400; break; - case 460800: rate = ftdi_8u232am_b460800; break; - case 921600: rate = ftdi_8u232am_b921600; break; - default: - rate = ftdi_sio_b19200; - TRACE_ALWAYS("= set_line_coding_ftdi: Datarate:%d is not supported " - "by this hardware. Defaulted to %d\n", - line_coding->speed, rate); - break; - } - } - - status = (*usb_m->send_request)(usd->dev, - USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, - FTDI_SIO_SET_BAUD_RATE, rate, - FTDI_PIT_DEFAULT, 0, 0, 0, &len1); - if(status != B_OK) - TRACE_ALWAYS("= set_line_coding_ftdi: datarate set request failed:%08x", - status); - - switch(line_coding->stopbits){ - case LC_STOP_BIT_2: data = FTDI_SIO_SET_DATA_STOP_BITS_2; break; - case LC_STOP_BIT_1: data = FTDI_SIO_SET_DATA_STOP_BITS_1; break; - default: - TRACE_ALWAYS("= set_line_coding_ftdi: Wrong stopbits param:%d", - line_coding->stopbits); - break; - } - - switch(line_coding->parity){ - case LC_PARITY_NONE: data |= FTDI_SIO_SET_DATA_PARITY_NONE; break; - case LC_PARITY_EVEN: data |= FTDI_SIO_SET_DATA_PARITY_EVEN; break; - case LC_PARITY_ODD: data |= FTDI_SIO_SET_DATA_PARITY_ODD; break; - default: - TRACE_ALWAYS("= set_line_coding_ftdi: Wrong parity param:%d", - line_coding->parity); - break; - } - - switch(line_coding->databits){ - case 8: data |= FTDI_SIO_SET_DATA_BITS(8); break; - case 7: data |= FTDI_SIO_SET_DATA_BITS(7); break; - default: - TRACE_ALWAYS("= set_line_coding_ftdi: Wrong databits param:%d", - line_coding->databits); - break; - } - - status = (*usb_m->send_request)(usd->dev, - USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, - FTDI_SIO_SET_DATA, data, - FTDI_PIT_DEFAULT, 0, 0, 0, &len2); - if(status != B_OK) - TRACE_ALWAYS("= set_line_coding_ftdi: data set request failed:%08x", - status); - - TRACE_FUNCRET("< set_line_coding_ftdi returns:%08x\n", status); - return status; -} - -status_t set_control_line_state_ftdi(usb_serial_device *usd, uint16 state){ - status_t status = B_OK; - int32 ctrl; - size_t len = 0; - TRACE_FUNCALLS("> set_control_line_state_ftdi(%08x, %04x)\n", usd, state); - - ctrl = (state & CLS_LINE_RTS) ? - FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW; - ctrl |= (state & CLS_LINE_DTR) ? - FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW; - status = (*usb_m->send_request)(usd->dev, - USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, - FTDI_SIO_MODEM_CTRL, ctrl, - FTDI_PIT_DEFAULT, 0, 0, 0, &len); - if(status != B_OK) - TRACE_ALWAYS("= set_control_line_state_ftdi: control set request " - "failed:%08x", status); - - TRACE_FUNCRET("< set_control_line_state_ftdi returns:%08x\n", status); - return status; -} - -void on_read_ftdi(usb_serial_device *usd, char **buf, size_t *num_bytes){ - usd->spec.ftdi.status_msr = FTDI_GET_MSR(*buf); - usd->spec.ftdi.status_lsr = FTDI_GET_LSR(*buf); - TRACE("MSR:%02x LSR:%02x\n", usd->spec.ftdi.status_msr, - usd->spec.ftdi.status_lsr); - *buf += 2; - *num_bytes -= 2; -} - -void on_write_ftdi(usb_serial_device *usd, const char *buf, - size_t *num_bytes){ - char *buf_to = usd->write_buffer; - int hdrlen = usd->spec.ftdi.hdrlen; - TRACE("hdrlen:%d\n", hdrlen); - if(*num_bytes > usd->write_buffer_size - hdrlen) - *num_bytes = usd->write_buffer_size - hdrlen; - if(hdrlen > 0) - *buf_to = FTDI_OUT_TAG(*num_bytes, FTDI_PIT_DEFAULT); - memcpy(buf_to + hdrlen, buf, *num_bytes); - *num_bytes += hdrlen; -} - -void on_close_ftdi(usb_serial_device *usd){ - TRACE_FUNCALLS("> on_close_ftdi(%08x)\n", usd); - (*usb_m->cancel_queued_transfers)(usd->pipe_read); - (*usb_m->cancel_queued_transfers)(usd->pipe_write); -} - diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.h b/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.h deleted file mode 100644 index 5f80bb1c48..0000000000 --- a/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2003 by Siarzhuk Zharski - * Distributed under the terms of the MIT License. - * - */ - -#ifndef _USB_FTDI_H_ - #define _USB_FTDI_H_ - -#define VND_FTDI 0x0403 - -#define PROD_8U100AX 0x8372 -#define PROD_8U232AM 0x6001 - -#define FTDI_BUF_SIZE 0x40 - -status_t add_ftdi_device(usb_serial_device *usd, - const usb_configuration_info *uci); -status_t reset_ftdi_device(usb_serial_device *usd); -status_t set_line_coding_ftdi(usb_serial_device *usd, - usb_serial_line_coding *line_coding); -status_t set_control_line_state_ftdi(usb_serial_device *usd, uint16 state); -void on_read_ftdi(usb_serial_device *usd, char **buf, size_t *num_bytes); -void on_write_ftdi(usb_serial_device *usd, const char *buf, size_t *num_bytes); -void on_close_ftdi(usb_serial_device *usd); - -#endif //_USB_FTDI_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/kernel_cpp.h b/src/add-ons/kernel/drivers/ports/usb_serial/kernel_cpp.h new file mode 100644 index 0000000000..7d7b025872 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_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_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/klsi.c b/src/add-ons/kernel/drivers/ports/usb_serial/klsi.c deleted file mode 100644 index 275e285fa5..0000000000 --- a/src/add-ons/kernel/drivers/ports/usb_serial/klsi.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 2003 by Siarzhuk Zharski - * Distributed under the terms of the MIT License. - * - */ - -#include -#include -#include -#include -#include - -#include "driver.h" -#include "klsi.h" - -status_t add_klsi_device(usb_serial_device *usd, - const usb_configuration_info *uci) -{ - struct usb_endpoint_info *comm_epi = NULL; - struct usb_endpoint_info *data_out_epi = NULL; - struct usb_endpoint_info *data_in_epi = NULL; - const usb_device_descriptor *ddesc; - status_t status = ENODEV; - uint32 i = 0; - - TRACE_FUNCALLS("> add_klsi_device(%08x, %08x)\n", usd, uci); - - if(uci->interface_count){ - struct usb_interface_info *uii = uci->interface[0].active; - for(i = 0; i < uii->endpoint_count; i++){ - if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_INTERRUPT){ - if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN) - == USB_EP_ADDR_DIR_IN /*USB_EP_ADDR_DIR_OUT = 0x0*/){ - TRACE("add_klsi_device:comm endpoint at %d\n", i); - comm_epi = &uii->endpoint[i]; - } - } - } - - for(i = 0; i < uii->endpoint_count; i++){ - if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_BULK){ - if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN) - == USB_EP_ADDR_DIR_IN){ - TRACE("add_klsi_device:in endpoint at %d\n", i); - data_in_epi = &uii->endpoint[i]; -// usd->read_buffer_size = uii->endpoint[i].descr->max_packet_size; - }else{ - if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN) - == USB_EP_ADDR_DIR_OUT){ - TRACE("add_klsi_device:out endpoint at %d\n", i); - data_out_epi = &uii->endpoint[i]; -// usd->write_buffer_size = uii->endpoint[i].descr->max_packet_size; - } - } - } - } - - if(comm_epi && data_in_epi && data_out_epi){ - usd->read_buffer_size = - usd->write_buffer_size = - usd->interrupt_buffer_size = ROUNDUP(KLSI_BUF_SIZE, 16); - status = add_device(usd, uci, comm_epi, data_out_epi, data_in_epi); - } - } - - TRACE_FUNCRET("< add_klsi_device returns:%08x\n", status); - return status; -} - -status_t reset_klsi_device(usb_serial_device *usd){ - status_t status; - size_t len = 0; - TRACE_FUNCALLS("> reset_klsi_device(%08x)\n", usd); - - status = (*usb_m->send_request)(usd->dev, - USB_REQTYPE_VENDOR | USB_REQTYPE_INTERFACE_OUT, - KLSI_CONF_REQUEST, - KLSI_CONF_REQUEST_READ_ON, 0, 0, - 0, 0, &len); - TRACE_FUNCRET("< reset_klsi_device returns:%08x\n", status); - return status; -} - -status_t set_line_coding_klsi(usb_serial_device *usd, - usb_serial_line_coding *line_coding){ - status_t status = B_OK; - uint8 rate; - size_t len1 = 0, len2 = 0; - uint8 coding_packet[5]; - TRACE_FUNCALLS("> set_line_coding_klsi(%08x, {%d, %02x, %02x, %02x})\n", - usd, line_coding->speed, - line_coding->stopbits, - line_coding->parity, - line_coding->databits); - - coding_packet[0] = 5; /* size */ - switch (line_coding->speed){ - case 300: rate = klsi_sio_b300; break; - case 600: rate = klsi_sio_b600; break; - case 1200: rate = klsi_sio_b1200; break; - case 2400: rate = klsi_sio_b2400; break; - case 4800: rate = klsi_sio_b4800; break; - case 9600: rate = klsi_sio_b9600; break; - case 19200: rate = klsi_sio_b19200; break; - case 38400: rate = klsi_sio_b38400; break; - case 57600: rate = klsi_sio_b57600; break; - case 115200: rate = klsi_sio_b115200; break; - default: - rate = klsi_sio_b19200; - TRACE_ALWAYS("= set_line_coding_klsi: Datarate:%d is not supported " - "by this hardware. Defaulted to %d\n", - line_coding->speed, rate); - break; - } - coding_packet[1] = rate; - /* only 7,8 */ - coding_packet[2] = line_coding->databits; - /* unknown */ - coding_packet[3] = 0; - coding_packet[4] = 1; - - status = (*usb_m->send_request)(usd->dev, - USB_REQTYPE_VENDOR | USB_REQTYPE_INTERFACE_OUT, - KLSI_SET_REQUEST, 0, 0, 0, - coding_packet, sizeof(coding_packet), &len1); - if(status != B_OK) - TRACE_ALWAYS("= set_line_coding_ftdi: datarate set request failed:%08x", - status); - - return status; -} - -status_t set_control_line_state_klsi(usb_serial_device *usd, uint16 state){ - status_t status = B_OK; - return status; -} - - -void on_read_klsi(usb_serial_device *usd, char **buf, size_t *num_bytes){ - size_t num; - if (*num_bytes <= 2) { - *num_bytes = 0; - return; - } - num = B_LENDIAN_TO_HOST_INT16(*(uint16*)(*buf)); - *num_bytes = MIN(num, (*num_bytes - 2)); - *buf += 2; -} - -void on_write_klsi(usb_serial_device *usd, const char *buf, size_t *num_bytes){ - if(*num_bytes > usd->write_buffer_size) - *num_bytes = usd->write_buffer_size; - if(*num_bytes > 62) - *num_bytes = 62; -*num_bytes = 6; - *((uint16*)usd->write_buffer) = B_HOST_TO_LENDIAN_INT16(*num_bytes); - memcpy(usd->write_buffer+2, buf, *num_bytes); -memcpy(usd->write_buffer+2, "ATDT0\n", 6); - *num_bytes = 64; -} - -void on_close_klsi(usb_serial_device *usd){ - status_t status; - size_t len = 0; - TRACE_FUNCALLS("> on_close_klsi(%08x)\n", usd); - status = (*usb_m->send_request)(usd->dev, - USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, - KLSI_CONF_REQUEST, - KLSI_CONF_REQUEST_READ_OFF, 0, 0, - 0, 0, &len); - (*usb_m->cancel_queued_transfers)(usd->pipe_read); - (*usb_m->cancel_queued_transfers)(usd->pipe_write); -} diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/klsi.h b/src/add-ons/kernel/drivers/ports/usb_serial/klsi.h deleted file mode 100644 index 827da8fc59..0000000000 --- a/src/add-ons/kernel/drivers/ports/usb_serial/klsi.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2003-2004 by Siarzhuk Zharski - * Distributed under the terms of the MIT License. - * - */ - -#ifndef _USB_KLSI_H_ - #define _USB_KLSI_H_ - -#define VND_PALM 0x0830 -#define VND_KLSI 0x05e9 - -#define PROD_PALM_CONNECT 0x0080 -#define PROD_KLSI_KL5KUSB105D 0x00c0 - -#define KLSI_SET_REQUEST 0x01 -#define KLSI_POLL_REQUEST 0x02 -#define KLSI_CONF_REQUEST 0x03 -#define KLSI_CONF_REQUEST_READ_ON 0x03 -#define KLSI_CONF_REQUEST_READ_OFF 0x02 - -// not sure -#define KLSI_BUF_SIZE 64 - -enum { - klsi_sio_b115200 = 0, - klsi_sio_b57600 = 1, - klsi_sio_b38400 = 2, - klsi_sio_b19200 = 4, - klsi_sio_b9600 = 6, - /* unchecked */ - klsi_sio_b4800 = 8, - klsi_sio_b2400 = 9, - klsi_sio_b1200 = 10, - klsi_sio_b600 = 11, - klsi_sio_b300 = 12, -}; - - -status_t add_klsi_device(usb_serial_device *usd, - const usb_configuration_info *uci); -status_t reset_klsi_device(usb_serial_device *usd); -status_t set_line_coding_klsi(usb_serial_device *usd, - usb_serial_line_coding *line_coding); - -status_t set_control_line_state_klsi(usb_serial_device *usd, uint16 state); -void on_read_klsi(usb_serial_device *usd, char **buf, size_t *num_bytes); -void on_write_klsi(usb_serial_device *usd, const char *buf, size_t *num_bytes); -void on_close_klsi(usb_serial_device *usd); - -#endif //_USB_PROLIFIC_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/prolific.c b/src/add-ons/kernel/drivers/ports/usb_serial/prolific.c deleted file mode 100644 index 028c271ef9..0000000000 --- a/src/add-ons/kernel/drivers/ports/usb_serial/prolific.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2003 by Siarzhuk Zharski - * Distributed under the terms of the MIT License. - * - */ - -#include -#include -#include -#include - -#include "driver.h" -#include "prolific.h" - -status_t add_prolific_device(usb_serial_device *usd, - const usb_configuration_info *uci) -{ - struct usb_endpoint_info *comm_epi = NULL; - struct usb_endpoint_info *data_out_epi = NULL; - struct usb_endpoint_info *data_in_epi = NULL; - const usb_device_descriptor *ddesc; - status_t status = ENODEV; - uint32 i = 0; - - TRACE_FUNCALLS("> add_prolific_device(%08x, %08x)\n", usd, uci); - - /* check for device type. - * Linux checks for type 0, 1 and HX, but handles 0 and 1 the same. - * We'll just check for HX then. - */ - if ((ddesc = (*usb_m->get_device_descriptor)(usd->dev))){ - usd->spec.prolific.is_HX = (ddesc->device_class != 0x02 && - ddesc->max_packet_size_0 == 0x40); - } - - if(uci->interface_count){ - struct usb_interface_info *uii = uci->interface[0].active; - for(i = 0; i < uii->endpoint_count; i++){ - if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_INTERRUPT){ - if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN) - == USB_EP_ADDR_DIR_IN /*USB_EP_ADDR_DIR_OUT = 0x0*/){ - TRACE("add_prolific_device:comm endpoint at %d\n", i); - comm_epi = &uii->endpoint[i]; - } - } - } - /*They say that USB-RSAQ1 has 2 interfaces */ - if(uci->interface_count == 2){ - uii = uci->interface[1].active; - } - - for(i = 0; i < uii->endpoint_count; i++){ - if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_BULK){ - if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN) - == USB_EP_ADDR_DIR_IN){ - TRACE("add_prolific_device:in endpoint at %d\n", i); - data_in_epi = &uii->endpoint[i]; - }else{ - if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN) - == USB_EP_ADDR_DIR_OUT){ - TRACE("add_prolific_device:out endpoint at %d\n", i); - data_out_epi = &uii->endpoint[i]; - } - } - } - } - - if(comm_epi && data_in_epi && data_out_epi){ - usd->read_buffer_size = - usd->write_buffer_size = - usd->interrupt_buffer_size = ROUNDUP(PROLIFIC_BUF_SIZE, 16); - status = add_device(usd, uci, comm_epi, data_out_epi, data_in_epi); - } - } - - TRACE_FUNCRET("< add_prolific_device returns:%08x\n", status); - return status; -} - -struct req_item { - uint8 requestType; - uint8 request; - uint16 value; - uint16 index; -}; - -#define PLRT_O (USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT) -#define PLRT_I (USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN) - -/* Linux sends all those, and it seems to work for me */ -/* see drivers/usb/serial/pl2303.c */ -static struct req_item pl_reset_common_reqs[] = { - {PLRT_I, PROLIFIC_SET_REQUEST, 0x8484, 0}, - {PLRT_O, PROLIFIC_SET_REQUEST, 0x0404, 0}, - {PLRT_I, PROLIFIC_SET_REQUEST, 0x8484, 0}, - {PLRT_I, PROLIFIC_SET_REQUEST, 0x8383, 0}, - {PLRT_I, PROLIFIC_SET_REQUEST, 0x8484, 0}, - {PLRT_O, PROLIFIC_SET_REQUEST, 0x0404, 1}, - {PLRT_I, PROLIFIC_SET_REQUEST, 0x8484, 0}, - {PLRT_I, PROLIFIC_SET_REQUEST, 0x8383, 0}, - {PLRT_O, PROLIFIC_SET_REQUEST, 0x0000, 1}, - {PLRT_O, PROLIFIC_SET_REQUEST, 0x0001, 0} -}; -static struct req_item pl_reset_common_hx[] = { - {PLRT_O, PROLIFIC_SET_REQUEST, 2, 0x44}, - {PLRT_O, PROLIFIC_SET_REQUEST, 8, 0}, - {PLRT_O, PROLIFIC_SET_REQUEST, 0, 0} -}; -static struct req_item pl_reset_common_nhx[] = { - {PLRT_O, PROLIFIC_SET_REQUEST, 2, 0x24} -}; - -static status_t usb_send_requ_list(const usb_device *dev, struct req_item *list, size_t len){ - uint32 i; - status_t status; - for (i = 0; i < len; i++){ - char buf[10]; - bool o = (list[i].requestType == PLRT_O); - size_t buflen = 1; - status = (*usb_m->send_request)(dev, - list[i].requestType, - list[i].request, - list[i].value, - list[i].index, - 0, o?0:buf, o?0:buflen, &buflen); - TRACE("usb_send_requ_list: reqs[%d]: %08lx\n", i, status); - } - return B_OK; -} - -status_t reset_prolific_device(usb_serial_device *usd){ - status_t status; - TRACE_FUNCALLS("> reset_prolific_device(%08x)\n", usd); - - status = usb_send_requ_list(usd->dev, pl_reset_common_reqs, SIZEOF(pl_reset_common_reqs)); - if (usd->spec.prolific.is_HX) - status = usb_send_requ_list(usd->dev, pl_reset_common_hx, SIZEOF(pl_reset_common_hx)); - else - status = usb_send_requ_list(usd->dev, pl_reset_common_nhx, SIZEOF(pl_reset_common_nhx)); - - status = B_OK; /* discard */ - TRACE_FUNCRET("< reset_prolific_device returns:%08x\n", status); - return status; -} diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/prolific.h b/src/add-ons/kernel/drivers/ports/usb_serial/prolific.h deleted file mode 100644 index 10e86ab193..0000000000 --- a/src/add-ons/kernel/drivers/ports/usb_serial/prolific.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2003-2004 by Siarzhuk Zharski - * Distributed under the terms of the MIT License. - * - */ - -#ifndef _USB_PROLIFIC_H_ - #define _USB_PROLIFIC_H_ - -#define VND_PROLIFIC 0x067b -#define VND_IODATA 0x04bb -#define VND_ATEN 0x0557 -#define VND_TDK 0x04bf -#define VND_RATOC 0x0584 -#define VND_ELECOM 0x056e -#define VND_SOURCENEXT 0x0833 -#define VND_HAL 0x0b41 - -#define PROD_IODATA_USBRSAQ 0x0a03 -#define PROD_PROLIFIC_RSAQ2 0x04bb -#define PROD_ATEN_UC232A 0x2008 -#define PROD_PROLIFIC_PL2303 0x2303 -#define PROD_TDK_UHA6400 0x0117 -#define PROD_RATOC_REXUSB60 0xb000 -#define PROD_ELECOM_UCSGT 0x5003 -#define PROD_SOURCENEXT_KEIKAI8 0x039f -#define PROD_SOURCENEXT_KEIKAI8_CHG 0x012e -#define PROD_HAL_IMR001 0x0011 - -// dobavit?!!!!!!!!!!!!! -// { 0, 0, 0, 0x0eba, 0x1080 }, // ITEGNO -// { 0, 0, 0, 0x0df7, 0x2620 } // MA620 - -#define PROLIFIC_SET_REQUEST 0x01 - -#define PROLIFIC_BUF_SIZE 0x100 - -status_t add_prolific_device(usb_serial_device *usd, - const usb_configuration_info *uci); -status_t reset_prolific_device(usb_serial_device *usd); - -#endif //_USB_PROLIFIC_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/tracing.c b/src/add-ons/kernel/drivers/ports/usb_serial/tracing.c deleted file mode 100644 index 33075b1a3c..0000000000 --- a/src/add-ons/kernel/drivers/ports/usb_serial/tracing.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2003 by Siarzhuk Zharski - * Distributed under the terms of the MIT License. - * - */ - -#include -#include -#include - -#include //sprintf -#include //posix file i/o - create, write, close -#include - - -#include "driver.h" -//#include "dano_hack.h" - -#if DEBUG -bool b_log = true; -#else -bool b_log = false; -#endif -bool b_log_file = false; -bool b_log_append = false; -bool b_log_funcalls = false; -bool b_log_funcret = false; -bool b_log_funcres = false; -bool b_acm_support = true; - -static const char *private_log_path="/boot/home/"DRIVER_NAME".log"; -static sem_id loglock; - -void load_setting(){ - void *settingshandle; - settingshandle = load_driver_settings(DRIVER_NAME); -#if !DEBUG - b_log = get_driver_boolean_parameter( - settingshandle, "debug_output", b_log, true); -#endif - b_log_file = get_driver_boolean_parameter( - settingshandle, "debug_output_in_file", b_log_file, true); - b_log_append = ! get_driver_boolean_parameter( - settingshandle, "debug_output_file_rewrite", !b_log_append, true); - b_log_funcalls = get_driver_boolean_parameter( - settingshandle, "debug_trace_func_calls", b_log_funcalls, false); - b_log_funcret = get_driver_boolean_parameter( - settingshandle, "debug_trace_func_returns", b_log_funcret, false); - b_log_funcres = get_driver_boolean_parameter( - settingshandle, "debug_trace_func_results", b_log_funcres, false); - b_acm_support = get_driver_boolean_parameter( - settingshandle, "support_acm_devices", b_acm_support, true); - - unload_driver_settings(settingshandle); -} - -void create_log(){ - int flags = O_WRONLY | O_CREAT | ((!b_log_append) ? O_TRUNC : 0); - if(!b_log_file) - return; - close(open(private_log_path, flags, 0666)); - loglock = create_sem(1, DRIVER_NAME"-logging"); -} - -void usb_serial_trace(bool b_force, char *fmt, ...){ - if(!(b_force || b_log)) - return; - { - va_list arg_list; - static char *prefix = "\33[32m"DRIVER_NAME":\33[0m"; - static char buf[1024]; - char *buf_ptr = buf; - if(!b_log_file){ - strcpy(buf, prefix); - buf_ptr += strlen(prefix); - } - - va_start(arg_list, fmt); - vsprintf(buf_ptr, fmt, arg_list); - va_end(arg_list); - - if(b_log_file){ - int fd; - acquire_sem(loglock); - fd = open(private_log_path, O_WRONLY | O_APPEND); - write(fd, buf, strlen(buf)); - close(fd); - release_sem(loglock); - } - else - dprintf(buf); - } -} - -void trace_ddomain(struct ddomain *dd){ - TRACE("struct ddomain\n" - " ddrover: %08x\n" - " bg:%d, locked:%d\n", dd->r, dd->bg, dd->locked); -} - -void trace_termios(struct termios *tios){ - TRACE("struct termios\n" - " c_iflag:%08x\n" - " c_oflag:%08x\n" - " c_cflag:%08x\n" - " c_lflag:%08x\n" - " c_line: %08x\n" - " c_ixxxxx:%08x\n" - " c_oxxxxx:%08x\n" - " c_cc [%02x, %02x, %02x, %02x, %02x, %02x, " - "%02x, %02x, %02x, %02x, %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" - " buffer:%08x\n" - " bufsize:%d\n" - " count:%d\n" - " tail:%d\n" - " allocated: %d\n", - str->buffer, - str->bufsize, str->count, str->tail, - str->allocated); -} - -void trace_winsize(struct winsize *ws){ - TRACE("struct winsize\n" - " ws_row:%d\n" - " ws_col:%d\n" - " ws_xpixel:%d\n" - " ws_ypixel:%d\n", - ws->ws_row, ws->ws_col, ws->ws_xpixel, ws->ws_ypixel); -} - -void trace_tty(struct tty *tty){ - TRACE("\n>> STRUCT tty\n" - " nopen:%d, flags:%08x,\n", - tty->nopen, tty->flags); - - TRACE("\n ddomain dd:\n"); - trace_ddomain(&tty->dd); - TRACE("\n ddomain ddi:\n"); - trace_ddomain(&tty->ddi); - - TRACE(" pgid: %08x\n", tty->pgid); - - TRACE("\n termios t:"); - trace_termios(&tty->t); - - TRACE(" iactivity: %d, ibusy:%d\n", tty->iactivity, tty->ibusy); - - TRACE("\n str istr:\n"); - trace_str(&tty->istr); - TRACE("\n str rstr:\n"); - trace_str(&tty->rstr); - TRACE("\n str ostr:\n"); - trace_str(&tty->ostr); - - TRACE("\n winsize wsize:\n"); - trace_winsize(&tty->wsize); - - TRACE(" service: %08x\n", tty->service); - TRACE("\n<< STRUCT tty\n"); -} diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/tracing.h b/src/add-ons/kernel/drivers/ports/usb_serial/tracing.h deleted file mode 100644 index e15ab9ee67..0000000000 --- a/src/add-ons/kernel/drivers/ports/usb_serial/tracing.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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_setting(); -void create_log(); -void usb_serial_trace(bool b_force, char *fmt, ...); - -#define TRACE_ALWAYS(x...) usb_serial_trace(true, x); -#define TRACE(x...) usb_serial_trace(false, x); - -extern bool b_log_funcalls; -#define TRACE_FUNCALLS(x...)\ - { if(b_log_funcalls) usb_serial_trace(false, x);} - -extern bool b_log_funcret; -#define TRACE_FUNCRET(x...)\ - { if(b_log_funcret) usb_serial_trace(false, x);} - -extern bool b_log_funcres; -#define TRACE_FUNCRES(func, param)\ - { if(b_log_funcres) 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); - -extern bool b_acm_support; - -#endif//_USB_SERIAL_TRACING_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.settings.sample b/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.settings.sample index 2e008c263d..f495955be7 100644 --- a/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.settings.sample +++ b/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.settings.sample @@ -1,37 +1,33 @@ # # The sample USB serial driver settings file # -# Rename it to usb_serial and put into +# Rename it to usb_serial and put it into # /boot/home/config/settings/kernel/drivers/ -# After restarting your system the new settings will works. +# After restarting your system the new settings will be applied. -#support_acm_devices - if you have other ACM driver in your system you can disable -# ACM support by setting this key to "false". The default value is "true" - the ACM -# support is activated. -#support_acm_devices true - -# Following settings are for debugging purposes. +# The following settings are for debugging purposes. # Debug output - this is a possibility to view some kind of development related # information - error and warning messages etc. -# debug_output - activates debug output. The debug builds has debug output -# activated by default and this key has no effect on it. The release builds requires -# to activate this if you want to see debug messages in syslog or in private log file. +# debug_output - activates debug output. The debug builds has debug output +# activated by default and this key has no effect on it. The release builds +# requires to activate this if you want to see debug messages in syslog or in +# private log file. # # debug_output true -# debug_output_in_file - activates writing of debug messages into private log file. -# The name of this file is /boot/home/usb_serial.log. If this key is set to true - no messages -# will be written into syslog. +# debug_output_in_file - activates writing of debug messages into private log +# file. The name of this file is /boot/home/usb_serial.log. If this key is set +# to true - no messages will be written into syslog. # # debug_output_in_file true -# debug_output_file_rewrite - activates rewriting of private log file on -# calling driver_init() syscall. By default this set in false. +# debug_output_file_rewrite - activates rewriting of private log file on +# calling driver_init() syscall. By default this set in false. # # debug_output_file_rewrite false -# debug_trace_func_calls - the information about driver functions calls +# debug_trace_func_calls - the information about driver functions calls # will be traced. Would you like to see internals? Then activate this. -# +# # debug_trace_func_calls true