From 5f470189bcbe8eb952d88c0b41f79d7536d0a844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Thu, 28 Jun 2007 23:15:58 +0000 Subject: [PATCH] This should support KLSI KL5KUSB105D based adapters, like that usb-to-serial Palm (for use with serial craddle) I got here. If I understood the linux driver correctly it should work but it seems I didn't yet :) For now it only lights the Terminal Ready light on my modem, doesn't get any data sent. Is it me or the semantics with the on_write() hook is broken ? (it's made to add headers/footers to buffers, but then header size is counted as written data, while it's not data as sent to the driver...) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21522 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/drivers/ports/usb_serial/Jamfile | 1 + .../kernel/drivers/ports/usb_serial/driver.c | 13 ++ .../kernel/drivers/ports/usb_serial/driver.h | 2 + .../kernel/drivers/ports/usb_serial/klsi.c | 173 ++++++++++++++++++ .../kernel/drivers/ports/usb_serial/klsi.h | 51 ++++++ 5 files changed, 240 insertions(+) create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/klsi.c create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/klsi.h diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/Jamfile b/src/add-ons/kernel/drivers/ports/usb_serial/Jamfile index 5441c37813..b16073ef82 100644 --- a/src/add-ons/kernel/drivers/ports/usb_serial/Jamfile +++ b/src/add-ons/kernel/drivers/ports/usb_serial/Jamfile @@ -12,6 +12,7 @@ KernelAddon usb_serial : acm.c prolific.c ftdi.c + klsi.c ; AddResources usb_serial : usb_serial.rdef ; diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/driver.c b/src/add-ons/kernel/drivers/ports/usb_serial/driver.c index e5d973b2c0..f21e82db45 100644 --- a/src/add-ons/kernel/drivers/ports/usb_serial/driver.c +++ b/src/add-ons/kernel/drivers/ports/usb_serial/driver.c @@ -17,6 +17,7 @@ #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); @@ -132,6 +133,18 @@ usb_serial_hw usb_serial_hw_devices[] = { 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; diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/driver.h b/src/add-ons/kernel/drivers/ports/usb_serial/driver.h index 61792ca60a..fef4b524ec 100644 --- a/src/add-ons/kernel/drivers/ports/usb_serial/driver.h +++ b/src/add-ons/kernel/drivers/ports/usb_serial/driver.h @@ -144,6 +144,8 @@ struct _s_usb_serial_device{ 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*/ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/klsi.c b/src/add-ons/kernel/drivers/ports/usb_serial/klsi.c new file mode 100644 index 0000000000..275e285fa5 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/klsi.c @@ -0,0 +1,173 @@ +/* + * 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 new file mode 100644 index 0000000000..827da8fc59 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/klsi.h @@ -0,0 +1,51 @@ +/* + * 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_