Add support for Silicon Labs CP210x to usb_serial.
Not completely tested : my device has no control lines wired. RX/TX seems to work fine, at least. Inspiration from the Linux driver since there isn't any documentation avilable: http://lxr.free-electrons.com/source/drivers/usb/serial/cp210x.c The switch/case for VID/PID identification is getting quite long. Isn't there a better way to do it ? git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42860 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
fd4f34da56
commit
7117b2ea25
@ -14,6 +14,7 @@ KernelAddon usb_serial :
|
||||
FTDI.cpp
|
||||
KLSI.cpp
|
||||
Prolific.cpp
|
||||
Silicon.cpp
|
||||
;
|
||||
|
||||
AddResources usb_serial : usb_serial.rdef ;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "FTDI.h"
|
||||
#include "KLSI.h"
|
||||
#include "Prolific.h"
|
||||
#include "Silicon.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
@ -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,
|
||||
|
135
src/add-ons/kernel/drivers/ports/usb_serial/Silicon.cpp
Normal file
135
src/add-ons/kernel/drivers/ports/usb_serial/Silicon.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2011, Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
|
||||
* 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;
|
||||
}
|
127
src/add-ons/kernel/drivers/ports/usb_serial/Silicon.h
Normal file
127
src/add-ons/kernel/drivers/ports/usb_serial/Silicon.h
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2011, Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
|
||||
* 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_
|
Loading…
Reference in New Issue
Block a user