Not finding any previous work that has been done to create a USB host driver for the Silicon Labs CP2103, I'm undertaking this task myself and have made some very limited headway.
My hardware setup is an Arduino Uno with Oleg's USB host shield. On the other end of the USB cable is a Silicon Labs CP2103 development board.
My starting point is Oleg's board_test code from his rev1 usb_host_shield-master. To that I'm attempting to add some CP2103-specific commands, starting with trying to set the baud rate and flow control.
The code:
/* USB related */
//#include <Spi.h>
#include <Max3421e.h>
#include <Max3421e_constants.h>
#include <Usb.h>
#include "board_test.h" /* Board test messages */
#define CP2103_VendID 0x10C4
#define CP2103_ProdID 0xEA60
#define CP2103_RevID 0x0100
#define REQTYPE_HOST_TO_DEVICE 0x40
#define REQTYPE_HOST_TO_INTERFACE 0x41
#define REQTYPE_DEVICE_TO_HOST 0xc0
#define CP210X_IFC_ENABLE 0x00
#define CP210X_GET_BAUDRATE 0x1D
#define CP210X_SET_BAUDRATE 0x1E
#define CP210X_SET_FLOW 0x13
#define CP210X_GET_FLOW 0x14
#define USB_CTRL_SET_TIMEOUT 5000
#define UART_ENABLE 0x0001
typedef void (*PARSE)( uint8_t bytes );
//#define MAX_SS 10
void setup();
void loop();
MAX3421E Max;
USB Usb;
byte result;
byte tmp;
char data[16];
byte rcv_bytes;
void setup()
{
Serial.begin( 115200 );
Max.powerOn();
printProgStr( startBanner );
printProgStr( anykey_msg );
//Serial.print( Max.getvar(), DEC);
}
void loop()
{
DEV_RECORD devtable[ USB_NUMDEVICES + 1 ];
/* start tests */
Serial.println("revregcheck...");
if (!revregcheck()) test_halted();
Serial.println("now osc test...");
if (!osctest()) printProgStr(PSTR("OSCOK test failed. Check the oscillator"));
if (!usbtest()) printProgStr(PSTR("USB connection test failed. Check traces from USB connector to MAX3421E, as well as VBUS")); //never gets here
/* All tests passed */
Serial.println("\nLink is ready.\n\n");
Serial.println("Calling Usb.task()...");
Usb.Task();
// unsure if we need to first "open" the CP210x...
Serial.println("\nAttempting to open device...");
//clearData();
result = Usb.ctrlReq( 1, 0, REQTYPE_HOST_TO_DEVICE, CP210X_IFC_ENABLE, UART_ENABLE, 0x00, 0x0000, 0x00, NULL, USB_NAK_LIMIT);
if(result) {
Serial.print("Error: result of command is: 0x");
Serial.println(result);
}
//printData();
Serial.println("\nRead initial baud rate setting...");
clearData();
result = Usb.ctrlReq( 1, 0, REQTYPE_DEVICE_TO_HOST, CP210X_GET_BAUDRATE, 0x00, 0x00, 0x0000, 0x08, data, USB_NAK_LIMIT);
if(result) {
Serial.print("Error: result of command is: 0x");
Serial.println(result);
}
printData();
Serial.println("\nAttempting to set baud rate to 57600");
result = Usb.ctrlReq( 1, 0, REQTYPE_HOST_TO_DEVICE, CP210X_SET_BAUDRATE, 0xE1, 0x00, 0x0000, 0x00, NULL, USB_NAK_LIMIT);
if(result) {
Serial.print("Error: result of command is: 0x");
Serial.println(result);
}
else Serial.println("Success.");
Serial.println("Read back baud rate...");
clearData();
result = Usb.ctrlReq( 1, 0, REQTYPE_DEVICE_TO_HOST, CP210X_GET_BAUDRATE, 0x00, 0x00, 0x0000, 0x04, data, USB_NAK_LIMIT);
if(result) {
Serial.print("Error: result of command is: 0x");
Serial.println(result);
}
printData();
Serial.println("\nAttempting to set flow control...");
result = Usb.ctrlReq( 1, 0, REQTYPE_HOST_TO_DEVICE, CP210X_SET_FLOW, 0x41, 0x00, 0x00, 0x00, NULL, USB_NAK_LIMIT);
if(result) {
Serial.print("Error: result of command is: 0x");
Serial.println(result);
}
Serial.println("Read back flow control settings...");
clearData();
result = Usb.ctrlReq( 1, 0, REQTYPE_DEVICE_TO_HOST, CP210X_GET_FLOW, 0x00, 0x00, 0x0000, 0x10, data, USB_NAK_LIMIT);
if(result) {
Serial.print("Error: result of command is: 0x");
Serial.println(result);
}
printLongData();
Serial.println("\nAttempting to set baud rate to 115200:");
result = Usb.ctrlReq( 1, 0, REQTYPE_HOST_TO_DEVICE, CP210X_SET_BAUDRATE, 0xC2, 0x01, 0x00, 0x00, NULL, USB_NAK_LIMIT);
if(result) {
Serial.print("Error: result of command is: 0x");
Serial.println(result);
}
Serial.println("Now read back baud rate again to confirm change...");
clearData();
result = Usb.ctrlReq( 1, 0, REQTYPE_DEVICE_TO_HOST, CP210X_GET_BAUDRATE, 0x00, 0x00, 0x0000, 0x04, data, USB_NAK_LIMIT);
if(result) {
Serial.print("Error: result of command is: 0x");
Serial.println(result);
}
printData();
while(1); // stop here for now....
// issue transfer_IN commands at 8 bytes at a time... forever...
for(byte i=0; i<2; i++) {
Serial.println("\n\nAttempting to receive data...");
//byte USB::inTransfer( addr, ep, unsigned int nbytes, char* data, unsigned int nak_limit )
result = BCinTransfer( 1, 0, 8, data, USB_NAK_LIMIT);
Serial.print("Result of inTransfer command: 0x0");
Serial.println(result, HEX);
if(result == 0) {
for(byte i=0; i<8; i++) {
Serial.print(data[i]);
}
Serial.println(" ");
}
delay(1000);
}
while(1); // stop here for now....
}
Current challenges:
-
I can't seem to set the baud rate. I'm reading a baud rate value of 0x01C200, I think, which corresponds to 115200. But nothing I've done seems to be able to set that to another value, in this case half of that, 57600, or 0x00E100.
-
I don't think I'm having an effect on flow control. I'm trying to leverage a command from the Linux driver for this device, a snippet of which is:
if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
cp210x_get_config(port, REQTYPE_INTERFACE_TO_HOST,
CP210X_GET_FLOW, 0, modem_ctl, 16);
dev_dbg(dev, "%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x\n",
__func__, modem_ctl[0], modem_ctl[1],
modem_ctl[2], modem_ctl[3]);
if (cflag & CRTSCTS) {
modem_ctl[0] &= ~0x7B;
modem_ctl[0] |= 0x09;
modem_ctl[1] = 0x80;
dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__);
} else {
modem_ctl[0] &= ~0x7B;
modem_ctl[0] |= 0x01;
modem_ctl[1] |= 0x40;
dev_dbg(dev, "%s - flow control = NONE\n", __func__);
}
dev_dbg(dev, "%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x\n",
__func__, modem_ctl[0], modem_ctl[1],
modem_ctl[2], modem_ctl[3]);
cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_SET_FLOW, 0, modem_ctl, 16);
}
which is where I'm getting the value of 0x41.
Not finding much in the way of documentation for this device, I'm left guessing as to where to put values in the USB packets.
Until I can see that I'm successfully able to set the baud rate and flow control, I'm not able to make much progress toward the ultimate goal, which is to issue BulkIN transfers from the Silicon Labs chip. (The end application for all this is to be able to pull data, across USB, from a Xilinx FPGA development card. This card has a USB console port with this device on it.)
If anyone has suggestions about how to move this forward, I could really, really use your help.
Thanks!
Bryan