diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/Jamfile b/src/add-ons/kernel/drivers/ports/usb_serial/Jamfile index 1240a5a24e..8a85cbd402 100644 --- a/src/add-ons/kernel/drivers/ports/usb_serial/Jamfile +++ b/src/add-ons/kernel/drivers/ports/usb_serial/Jamfile @@ -14,6 +14,7 @@ KernelAddon usb_serial : FTDI.cpp KLSI.cpp Prolific.cpp + Silicon.cpp ; AddResources usb_serial : usb_serial.rdef ; diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp b/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp index 23a5bcfc37..0d76a31550 100644 --- a/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp +++ b/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp @@ -14,6 +14,7 @@ #include "FTDI.h" #include "KLSI.h" #include "Prolific.h" +#include "Silicon.h" #include @@ -801,6 +802,361 @@ SerialDevice::MakeDevice(usb_device device, uint16 vendorID, return new(std::nothrow) KLSIDevice(device, vendorID, productID, description); } + + case VENDOR_RENESAS: + { + switch (productID) { + case 0x0053: + description = "Renesas RX610 RX-Stick"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_AKATOM: + { + switch (productID) { + case 0x066A: + description = "AKTAKOM ACE-1001"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_PIRELLI: + { + switch (productID) { + case 0xE000: + case 0xE003: + description = "Pirelli DP-L10 GSM Mobile"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_CYPHERLAB: + { + switch (productID) { + case 0x1000: + description = "Cipherlab CCD Barcode Scanner"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_GEMALTO: + { + switch (productID) { + case 0x5501: + description = "Gemalto contactless smartcard reader"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_DIGIANSWER: + { + switch (productID) { + case 0x000A: + description = "Digianswer ZigBee MAC device"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_MEI: + { + switch (productID) { + case 0x1100: + case 0x1101: + description = "MEI Acceptor"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_DYNASTREAM: + { + switch (productID) { + case 0x1003: + case 0x1004: + case 0x1006: + description = "Dynastream ANT development board"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_KNOCKOFF: + { + switch (productID) { + case 0xAA26: + description = "Knock-off DCU-11"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_SIEMENS: + { + switch (productID) { + case 0x10C5: + description = "Siemens MC60"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_NOKIA: + { + switch (productID) { + case 0xAC70: + description = "Nokia CA-42"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_SILICON: + { + switch (productID) { + case 0x0F91: + case 0x1101: + case 0x1601: + case 0x800A: + case 0x803B: + case 0x8044: + case 0x804E: + case 0x8053: + case 0x8054: + case 0x8066: + case 0x806F: + case 0x807A: + case 0x80CA: + case 0x80DD: + case 0x80F6: + case 0x8115: + case 0x813D: + case 0x813F: + case 0x814A: + case 0x814B: + case 0x8156: + case 0x815E: + case 0x818B: + case 0x819F: + case 0x81A6: + case 0x81AC: + case 0x81AD: + case 0x81C8: + case 0x81E2: + case 0x81E7: + case 0x81E8: + case 0x81F2: + case 0x8218: + case 0x822B: + case 0x826B: + case 0x8293: + case 0x82F9: + case 0x8341: + case 0x8382: + case 0x83A8: + case 0x83D8: + case 0x8411: + case 0x8418: + case 0x846E: + case 0x8477: + case 0x85EA: + case 0x85EB: + case 0x8664: + case 0x8665: + case 0xEA60: + case 0xEA61: + case 0xEA71: + case 0xF001: + case 0xF002: + case 0xF003: + case 0xF004: + description = "Silicon Labs CP210x USB UART converter"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_SILICON2: + { + switch (productID) { + case 0xEA61: + description = "Silicon Labs GPRS USB Modem"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_SILICON3: + { + switch (productID) { + case 0xEA6A: + description = "Silicon Labs GPRS USB Modem 100EU"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_BALTECH: + { + switch (productID) { + case 0x9999: + description = "Balteck card reader"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_OWEN: + { + switch (productID) { + case 0x0004: + description = "Owen AC4 USB-RS485 Converter"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_CLIPSAL: + { + switch (productID) { + case 0x0303: + description = "Clipsal 5500PCU C-Bus USB interface"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_JABLOTRON: + { + switch (productID) { + case 0x0001: + description = "Jablotron serial interface"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_WIENER: + { + switch (productID) { + case 0x0010: + case 0x0011: + case 0x0012: + case 0x0015: + description = "W-IE-NE-R Plein & Baus GmbH device"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_WAVESENSE: + { + switch (productID) { + case 0xAAAA: + description = "Wavesense Jazz blood glucose meter"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_VAISALA: + { + switch (productID) { + case 0x0200: + description = "Vaisala USB instrument"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_ELV: + { + switch (productID) { + case 0xE00F: + description = "ELV USB I²C interface"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_WAGO: + { + switch (productID) { + case 0x07A6: + description = "WAGO 750-923 USB Service"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + case VENDOR_DW700: + { + switch (productID) { + case 0x9500: + description = "DW700 GPS USB interface"; + break; + } + + if (description != NULL) + goto SILICON; + break; + } + +SILICON: + return new(std::nothrow) SiliconDevice(device, vendorID, productID, + description); } return new(std::nothrow) ACMDevice(device, vendorID, productID, diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/Silicon.cpp b/src/add-ons/kernel/drivers/ports/usb_serial/Silicon.cpp new file mode 100644 index 0000000000..5f3a33e451 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/Silicon.cpp @@ -0,0 +1,135 @@ +/* + * Copyright 2011, Adrien Destugues + * Distributed under the terms of the MIT License. + */ + + +#include "Silicon.h" + + +static const int kBaudrateGeneratorFrequency = 0x384000; + + +SiliconDevice::SiliconDevice(usb_device device, uint16 vendorID, uint16 productID, + const char *description) + : SerialDevice(device, vendorID, productID, description) +{ +} + + +// Called for each configuration of the device. Return B_OK if the given +// configuration sounds like it is the usb serial one. +status_t +SiliconDevice::AddDevice(const usb_configuration_info *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_ENDPOINT_ATTR_BULK) { + if (endpoint->descr->endpoint_address & USB_ENDPOINT_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) { + status = B_OK; + } + } + return status; +} + + +// Called on opening the device - Good time to enable the UART ? +status_t +SiliconDevice::ResetDevice() +{ + uint16_t enableUart = 1; + return WriteConfig(ENABLE_UART, &enableUart, 2); +} + + +status_t +SiliconDevice::SetLineCoding(usb_cdc_line_coding *lineCoding) +{ + uint16_t divider = kBaudrateGeneratorFrequency / lineCoding->speed ; + status_t result = WriteConfig(SET_BAUDRATE_DIVIDER, ÷r, 2); + + if (result != B_OK) return result; + + uint16_t data = 0; + + switch (lineCoding->stopbits) { + case USB_CDC_LINE_CODING_1_STOPBIT: data = 0; break; + case USB_CDC_LINE_CODING_2_STOPBITS: data = 2; break; + default: + TRACE_ALWAYS("= SiliconDevice::SetLineCoding(): Wrong stopbits param: %d\n", + lineCoding->stopbits); + break; + } + + switch (lineCoding->parity) { + case USB_CDC_LINE_CODING_NO_PARITY: data |= 0 << 4; break; + case USB_CDC_LINE_CODING_EVEN_PARITY: data |= 2 << 4; break; + case USB_CDC_LINE_CODING_ODD_PARITY: data |= 1 << 4; break; + default: + TRACE_ALWAYS("= SiliconDevice::SetLineCoding(): Wrong parity param: %d\n", + lineCoding->parity); + break; + } + + data |= lineCoding->databits << 8; + + return WriteConfig(SET_LINE_FORMAT, &data, 2); +} + + +status_t +SiliconDevice::SetControlLineState(uint16 state) +{ + uint16_t control = 0; + control |= 0x0300; // We are updating DTR and RTS + control |= (state & USB_CDC_CONTROL_SIGNAL_STATE_RTS) ? 2 : 0; + control |= (state & USB_CDC_CONTROL_SIGNAL_STATE_DTR) ? 1 : 0; + + return WriteConfig(SET_STATUS, &control, 2); +} + + +status_t SiliconDevice::WriteConfig(CP210XRequest request, uint16_t* data, + size_t size) +{ + size_t replyLength = 0; + status_t result; + // Small requests (16 bits and less) use the "value" field for their data. + // Bigger ones use the actual buffer. + if (size <= 2) { + result = gUSBModule->send_request(Device(), + USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, request, data[0], 0, 0, + NULL, &replyLength); + } else { + result = gUSBModule->send_request(Device(), + USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, request, 0x0000, 0, + size, data, &replyLength); + } + + if (result != B_OK) { + TRACE_ALWAYS("= SiliconDevice request failed: 0x%08x (%s)\n", + result, strerror(result)); + } + + return result; +} diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/Silicon.h b/src/add-ons/kernel/drivers/ports/usb_serial/Silicon.h new file mode 100644 index 0000000000..3c1897dac4 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/Silicon.h @@ -0,0 +1,127 @@ +/* + * Copyright 2011, Adrien Destugues + * Distributed under the terms of the MIT License. + */ +#ifndef _USB_SILICON_H_ +#define _USB_SILICON_H_ + +#include "SerialDevice.h" + +class SiliconDevice : public SerialDevice { +public: + SiliconDevice(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_cdc_line_coding *coding); +virtual status_t SetControlLineState(uint16 state); + +private: +enum CP210XRequest { + ENABLE_UART = 0, + /* 1 to enable the UART function, 0 to disable + * (some Silicon Labs chips have other functions such as GPIOs) */ + + + SET_BAUDRATE_DIVIDER = 1, + GET_BAUDRATE_DIVIDER = 2, + /* + Baudrate base clock is 3686400 + + 3686400 / 32 = 115200 + ... + 3686400 / 384 = 9600 + */ + + SET_LINE_FORMAT = 3, + GET_LINE_FORMAT = 4, + /* + DataBits << 0x100 | Parity << 0x10 | StopBits + + Databits in [5,9] + Parity : + 0 = none + 1 = odd + 2 = even + 3 = mark + 4 = space + Stop bits: + 0 = 1 stop bit + 1 = 1.5 stop bits + 2 = 2 stop bits + */ + + SET_BREAK = 5, + /* 1 to enable, 0 to disable */ + + IMMEDIATE_CHAR = 6, + + SET_STATUS = 7, + GET_STATUS = 8, + /* + bit 0 = DTR + bit 1 = RTS + + bit 4 = CTS + bit 5 = DSR + bit 6 = RING + bit 7 = DCD + bit 8 = WRITE_DTR (unset to not touch DTR) + bit 9 = WRITE_RTS (unset to not touch RTS) + */ + + SET_XON = 9, + SET_XOFF = 10, + SET_EVENTMASK = 11, + GET_EVENTMASK = 12, + SET_CHAR = 13, + GET_CHARS = 14, + GET_PROPS = 15, + GET_COMM_STATUS = 16, + RESET = 17, + PURGE = 18, + + SET_FLOW = 19, + GET_FLOW = 20, + /* Hardware flow control setup */ + + EMBED_EVENTS = 21, + GET_EVENTSTATE = 22, + SET_CHARS = 0x19 +}; + +private: +status_t WriteConfig(CP210XRequest request, uint16_t* data, + size_t size); +}; + +#define VENDOR_RENESAS 0x045B +#define VENDOR_AKATOM 0x0471 +#define VENDOR_PIRELLI 0x0489 +#define VENDOR_CYPHERLAB 0x0745 +#define VENDOR_GEMALTO 0x08E6 +#define VENDOR_DIGIANSWER 0x08FD +#define VENDOR_MEI 0x0BED +#define VENDOR_DYNASTREAM 0x0FCF +#define VENDOR_KNOCKOFF 0x10A6 +#define VENDOR_SIEMENS 0x10AB +#define VENDOR_NOKIA 0x10B5 +#define VENDOR_SILICON 0x10C4 +#define VENDOR_SILICON2 0x10C5 +#define VENDOR_SILICON3 0x10CE +#define VENDOR_BALTECH 0x13AD +#define VENDOR_OWEN 0x1555 +#define VENDOR_CLIPSAL 0x166A +#define VENDOR_JABLOTRON 0x16D6 +#define VENDOR_WIENER 0x16DC +#define VENDOR_WAVESENSE 0x17F4 +#define VENDOR_VAISALA 0x1843 +#define VENDOR_ELV 0x18EF +#define VENDOR_WAGO 0x1BE3 +#define VENDOR_DW700 0x413C + + +#endif //_USB_SILICON_H_