FTDI Community

Please login or register.

Login with username, password and session length.
Advanced Search  

News:

Welcome to the FTDI Community!

Please read our Welcome Note

Technical Support enquires
please contact the team
@ FTDI Support


New Bridgetek Community is now open

Please note that we have created the Bridgetek Community to discuss all Bridgetek products e.g. EVE, MCU.

Please follow this link and create a new user account to get started.

Bridgetek Community

Show Posts

You can view here all posts made by this member. Note that you can only see posts made in areas to which you currently have access.

Messages - AndersG

Pages: [1]
1
OK. Thanks. Problem is that I do not have these keyboards here to test, but ordinary keyboards seem to work just fine. Redesigning to use somehing else than VNC2 is not an option at this point.

2
Wondering how one would go about troubleshooting this. The device is a keyboard adapter for legacy systems. It uses a VNC2 for USB and I modified the SPI sample so that it passes on keyboard and mouse data to the main processor, over SPI.

It has worked well with the Mice and Keyboards I have tested with. Someone else is betatesting the device and had problems with the following keyboards:

WK-610 a Mini USB keyboard
Keyboardio

I have three leds connected to the VNC2. One lights when there is a device on the bus:

if (usbhost_connect_state(hUsb) == PORT_STATE_ENUMERATED)

The other two flashes when it sees activity. With the abovementioned keyboards there is no activity

What could cause this?

3
OK. I think I have it working now, but feedback is appreciated. I have one thread per port, plus the setup thread that runs once a second.

Code: [Select]
/*
** Filename: USBHostHID2.c
**
** Handle 1..2 USB HID devices, passing on keypresses and mouse movements
** over SPI as packets. Packet format is:
** 0x13
** Packet length, 8 or 4
** first byte, ms nibble
** first byte, ls nibble
** etc
** 0x14
**
**
** Links/doc:
** http://joshp.no-ip.com:8080/vnc2/#issue2
*/

#include "USBHostHID2.h"

/* FTDI:STP Thread Prototypes */
vos_tcb_t *tcbFIRMWARE;
vos_tcb_t *tcbSETUP;

void firmware0();
void firmware1();
void setup();
/* FTDI:ETP */

/* FTDI:SDH Driver Handles */
VOS_HANDLE hUSBHOST_1; // USB Host Port 1
VOS_HANDLE hUSBHOST_2; // USB Host Port 2
VOS_HANDLE hUART; // UART Interface Driver
#ifdef USE_SPI
VOS_HANDLE hSPI_MASTER; // SPIMaster Interface Driver
#endif
/* FTDI:EDH */
// use our own driver handles to simplify code later
VOS_HANDLE hUsb[2];
int tick = 0;
/* Declaration for IOMUx setup function */
void iomux_setup(void);
//--------------------------- GLOBALS -------------------
// test buffer
char buf[64];
char *eol = "\r\n";
char replybuf[64];

unsigned char i;
unsigned short len;
unsigned short written;
unsigned char status;
unsigned char n0, n1, m;
unsigned char ch;
unsigned int replylen;
// GPIO and LEDs
unsigned char leds;

// device handle
usbhost_device_handle_ex ifDev;
// endpoint handles
usbhost_ep_handle_ex epInt[2], epCtrl[2];
// endpoint maxPacketLength values
unsigned char maxPack[2];

// completion semaphore and set semaphore list
//vos_semaphore_t semRead; // not used?

// Host Controller ioctl request block
usbhost_ioctl_cb_t hc_iocb;
usbhost_ioctl_cb_vid_pid_t hc_ioctVidPid;

// interrupt endpoint transfer descriptors for port 0 and 1
usbhost_xfer_t xfer0;
usbhost_xfer_t xfer1;

// UART ioctl request block
common_ioctl_cb_t uart_iocb;
#ifdef USE_SPI
// SPI Master ioctl request block
common_ioctl_cb_t spim_iocb;
#endif

// host controller device descriptor
usb_deviceRequest_t desc_dev;

// endpoint information
usbhost_ioctl_cb_ep_info_t epInfo;
//
vos_semaphore_t setupSem0; // Shows that port is set up
vos_semaphore_t setupSem1;
vos_semaphore_t endpointSem0;
vos_semaphore_t endpointSem1;
// ---------------------------------------------------------

/* Main code - entry point to firmware */
void main(void)
{
// Driver Declarations
// UART Driver configuration context
uart_context_t uartContext;
// USB Host configuration context
usbhost_context_t usbhostContext;

#ifdef USE_SPI
// SPI Master configuration context
spimaster_context_t spimContext;
#endif
// Kernel Initialisation
vos_init(50, VOS_TICK_INTERVAL, VOS_NUMBER_DEVICES);
vos_set_clock_frequency(VOS_48MHZ_CLOCK_FREQUENCY);
vos_set_idle_thread_tcb_size(512);

iomux_setup();

// Driver Initialisation
// Initialise UART
#ifdef USE_UART
uartContext.buffer_size = VOS_BUFFER_SIZE_128_BYTES;
uart_init(VOS_DEV_UART,&uartContext);
#endif
//
// SPI
#ifdef USE_SPI
spimContext.buffer_size = VOS_BUFFER_SIZE_128_BYTES;
spimaster_init(VOS_DEV_SPI_MASTER,&spimContext);
#endif

// Initialise USB Host
usbhostContext.if_count = 8;
usbhostContext.ep_count = 16;
usbhostContext.xfer_count = 2;
usbhostContext.iso_xfer_count = 2;
usbhost_init(VOS_DEV_USBHOST_1, VOS_DEV_USBHOST_2, &usbhostContext);

vos_init_semaphore(&setupSem0, 0);
vos_init_semaphore(&setupSem1, 0);

// Thread Creation, setup and on thread per port
tcbFIRMWARE = vos_create_thread_ex(21, 2048, firmware0, "Port0", 0);
tcbFIRMWARE = vos_create_thread_ex(21, 2048, firmware1, "Port1", 0);
tcbFIRMWARE = vos_create_thread_ex(20, 4096, setup, "Setup", 0);
//
vos_gpio_set_port_mode(GPIO_PORT_A, 0xff);  // set all as output
//
vos_start_scheduler();

main_loop:
goto main_loop;
}

/* FTDI:SSP Support Functions */

unsigned char usbhost_connect_state(VOS_HANDLE hUSB)
{
unsigned char connectstate = PORT_STATE_DISCONNECTED;
usbhost_ioctl_cb_t hc_iocb;

if (hUSB)
{
hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_GET_CONNECT_STATE;
hc_iocb.get        = &connectstate;
vos_dev_ioctl(hUSB, &hc_iocb);

    // repeat if connected to see if we move to enumerated
if (connectstate == PORT_STATE_CONNECTED)
{
vos_dev_ioctl(hUSB, &hc_iocb);
}
}
return connectstate;
}

/* FTDI:ESP */

void open_drivers(void)
{
// Code for opening and closing drivers - move to required places in Application Threads
hUSBHOST_1 = vos_dev_open(VOS_DEV_USBHOST_1);
hUSBHOST_2 = vos_dev_open(VOS_DEV_USBHOST_2);
#ifdef USE_UART
hUART = vos_dev_open(VOS_DEV_UART);
#endif
#ifdef USE_SPI
hSPI_MASTER = vos_dev_open(VOS_DEV_SPI_MASTER);
#endif
}

void attach_drivers(void)
{
/* FTDI:SUA Layered Driver Attach Function Calls */
/* FTDI:EUA */
}

void close_drivers(void)
{
// Driver Close
vos_dev_close(hUSBHOST_1);
vos_dev_close(hUSBHOST_2);
vos_dev_close(hUART);
#ifdef USE_SPI
vos_dev_close(hSPI_MASTER);
#endif
}

// Helpers

void message(char *msg)
{
#ifdef USE_UART
vos_dev_write(hUART, (unsigned char *) msg, strlen(msg), NULL);
#endif
}

void number(unsigned char val)
{
#ifdef USE_UART
char letter;
unsigned char nibble;

nibble = (val >> 4) + '0';

if (nibble > '9')
nibble += ('A' - '9' - 1);

vos_dev_write(hUART, &nibble, 1, NULL);
nibble = (val & 15) + '0';

if (nibble > '9')
nibble += ('A' - '9' - 1);

vos_dev_write(hUART, &nibble, 1, NULL);
#endif
}


//vos_semaphore_list_t *sem_list;        // pointer to semaphore list

//
// Thread for port 0
void firmware0(void)
{
unsigned char status0;
// Wait for the setup sem to finish...
vos_wait_semaphore(&setupSem0);
vos_delay_msecs(1000);
while(1)
{
if (epCtrl[0])
{
vos_init_semaphore(&endpointSem0,0);
n0 = -1;
memset(xfer0, 0, sizeof(xfer0));

xfer0.buf = buf;
xfer0.s = &endpointSem0;
xfer0.ep = epInt[0];
// Do not block on completion... we will wait on the sempaphore later
xfer0.flags = USBHOST_XFER_FLAG_NONBLOCKING | USBHOST_XFER_FLAG_ROUNDING;

while (1)
{
if (n0 != 1) // ie 0 or -1
{
xfer0.len = maxPack[0];
xfer0.cond_code = USBHOST_CC_NOTACCESSED;

status0 = vos_dev_read(hUsb[0], (unsigned char *) &xfer0, sizeof(usbhost_xfer_t), NULL);

if (status0 != USBHOST_OK)
{
message("Port 00 Read Failed - code ");
number(status0);
message(eol);
}
}

// Wait on a key press from  endpoint...
vos_wait_semaphore(&endpointSem0);
n0 = 0;

// Display data received
number(tick++);
message(" Port ");
number(n0);
message(" Data: ");

if (n0 == 0)
{
// sem1 has signalled
leds = leds | LED2;
vos_gpio_write_port(GPIO_PORT_A, leds);
replybuf[0] = 0x13;
replybuf[1] = (unsigned char)xfer0.len;
replylen = 2;
for (i = 0; i < xfer0.len; i++)
{
number(buf[i]);
ch = buf[i];
replybuf[replylen++] = (ch >> 4); // MSB
replybuf[replylen++] = (ch & 0x0f); // LSB
}
replybuf[replylen++] = 0x14;
#ifdef USE_SPI
vos_dev_write(hSPI_MASTER, (unsigned char *)replybuf, (uint16) replylen, NULL);
#endif
}
message(eol);
}
}
}
}

//
// Thread for port 1
void firmware1(void)
{
unsigned char status1;
// Wait for the setup sem to finish...
vos_wait_semaphore(&setupSem1);
vos_delay_msecs(1000);
while(1)
{
if (epCtrl[1])
{
vos_init_semaphore(&endpointSem1,0);
n1 = -1;
memset(xfer1, 0, sizeof(xfer1));

xfer1.buf = buf;
xfer1.s = &endpointSem1; //&endpointSem[1];
xfer1.ep = epInt[1];
//Do not block on completion... we will wait on the sempaphore later
xfer1.flags = USBHOST_XFER_FLAG_NONBLOCKING | USBHOST_XFER_FLAG_ROUNDING;

while (1)
{
if (n1 != 0) // ie 1 or -1
{
xfer1.len = maxPack[1];
xfer1.cond_code = USBHOST_CC_NOTACCESSED;

status1 = vos_dev_read(hUsb[1], (unsigned char *) &xfer1, sizeof(usbhost_xfer_t), NULL);

if (status1 != USBHOST_OK)
{
message("Port 01 Read Failed - code ");
number(status1);
message(eol);
//break;
}
}

// Wait on a key press from  endpoint...
vos_wait_semaphore(&endpointSem1);
n1 = 1;

// Display data received
number(tick++);
message(" Port ");
number(n1);
message(" Data: ");

if (n1 == 1)
{
// sem1 has signalled
leds = leds | LED3;
vos_gpio_write_port(GPIO_PORT_A, leds);
replybuf[0] = 0x13;
replybuf[1] = (unsigned char)xfer1.len;
replylen = 2;
for (i = 0; i < xfer1.len; i++)
{
number(buf[i]);
ch = buf[i];
replybuf[replylen++] = (ch >> 4); // MSB
replybuf[replylen++] = (ch & 0x0f); // LSB
}
replybuf[replylen++] = 0x14;
#ifdef USE_SPI
vos_dev_write(hSPI_MASTER, (unsigned char *)replybuf, (uint16) replylen, NULL);
#endif
}

message(eol);
}
}
}
}
// Setup thread, runs slowly and flags added devices through semaptĀ“hores
void setup(void)
{
int tick = 0;
int i = 0;
epInt[0] = NULL;
epCtrl[0] = NULL;
epInt[1] = NULL;
epCtrl[1] = NULL;

open_drivers();
hUsb[0] = hUSBHOST_1;
hUsb[1] = hUSBHOST_2;

#ifdef USE_UART
//uart_iocb.ioctl_code = VOS_IOCTL_COMMON_ENABLE_DMA;
//uart_iocb.set.param = DMA_ACQUIRE_AS_REQUIRED;
//vos_dev_ioctl(hUART, &uart_iocb);

// set baud rate
uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_BAUD_RATE;
uart_iocb.set.uart_baud_rate = UART_BAUD_9600; //UART_BAUD_115200
vos_dev_ioctl(hUART, &uart_iocb);

// set flow control
uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_FLOW_CONTROL;
uart_iocb.set.param = UART_FLOW_RTS_CTS;
vos_dev_ioctl(hUART, &uart_iocb);

// set data bits
uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_DATA_BITS;
uart_iocb.set.param = UART_DATA_BITS_8;
vos_dev_ioctl(hUART, &uart_iocb);

// set stop bits
uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_STOP_BITS;
uart_iocb.set.param = UART_STOP_BITS_1;
vos_dev_ioctl(hUART, &uart_iocb);

// set parity
uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_PARITY;
uart_iocb.set.param = UART_PARITY_NONE;
vos_dev_ioctl(hUART, &uart_iocb);
#endif
#ifdef USE_SPI
// set clock phase
spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_SCK_CPHA;
spim_iocb.set.param = SPI_MASTER_SCK_CPHA_0;
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
// set clock polarity
spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_SCK_CPOL;
spim_iocb.set.param = SPI_MASTER_SCK_CPOL_0;
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
// set data order
spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_DATA_ORDER;
spim_iocb.set.param = SPI_MASTER_DATA_ORDER_MSB;
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
// enable DMA
spim_iocb.ioctl_code = VOS_IOCTL_COMMON_ENABLE_DMA;
spim_iocb.set = DMA_ACQUIRE_AND_RETAIN;
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
// set clock rate
spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_SET_SCK_FREQUENCY;
spim_iocb.set.spi_master_sck_freq = 300000; // /10
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
// set auto toggle
spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_AUTO_TOGGLE_SS;
spim_iocb.set.param = SPI_MASTER_SS_AUTO_TOGGLE_ENABLE_SS_0;
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
#endif
message("Starting...\r\n");
#ifdef USE_SPI
message("With SPI...\r\n");
//vos_dev_write(hSPI_MASTER, "With SPI...\r\n", 13, NULL);
#endif
do
{
vos_delay_msecs(1000);

// check if USB port i is configured already
for (i = 0; i < 2; i++)
{
if (epCtrl[i] == NULL)
{
// user ioctl to see if selected USB port available
if (usbhost_connect_state(hUsb[i]) == PORT_STATE_ENUMERATED)
{
message("Enumeration complete Port ");
number(i);
message(eol);
leds = leds | LED1;
vos_gpio_write_port(GPIO_PORT_A, leds);

// user ioctl to find first hub device
hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_NEXT_HANDLE;
// find first device interface
hc_iocb.handle.dif = NULL;
// hc_iocb.set = &hc_ioctVidPid;
hc_iocb.get = &ifDev;
status = vos_dev_ioctl(hUsb[i], &hc_iocb);

if (status != USBHOST_OK)
{
message("No Device Found - code ");
number(status);
message(eol);
break;
}

// user ioctl to find control endpoint on this device
hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_CONTROL_ENDPOINT_HANDLE;
hc_iocb.handle.dif = ifDev;
hc_iocb.get = &epCtrl[i];

status = vos_dev_ioctl(hUsb[i], &hc_iocb);

if (status != USBHOST_OK)
{
message("No Control Endpoint Found - code ");
number(status);
message(eol);
break;
}

// user ioctl to find first interrupt endpoint on this device
hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_INT_IN_ENDPOINT_HANDLE;
hc_iocb.handle.dif = ifDev;
hc_iocb.get = &epInt[i];
status = vos_dev_ioctl(hUsb[i], &hc_iocb);

if (status != USBHOST_OK)
{
message("No interrupt Endpoint Found - code ");
number(status);
message(eol);
break;
}

// user ioctl to find interrupt endpoint on this device
hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_ENDPOINT_INFO;
hc_iocb.handle.ep = epInt[i];
hc_iocb.get = &epInfo;

status = vos_dev_ioctl(hUsb[i], &hc_iocb);

if (status != USBHOST_OK)
{
message("Interrupt Endpoint Info Not Found - code ");
number(status);
message(eol);
break;
}

maxPack[i] = epInfo.max_size;

desc_dev.bmRequestType = USB_BMREQUESTTYPE_HOST_TO_DEV |
USB_BMREQUESTTYPE_CLASS |
USB_BMREQUESTTYPE_INTERFACE;
desc_dev.bRequest = 0x0a; // USB_HID_REQUEST_CODE_SET_IDLE
desc_dev.wValue = 0; // Repeat rate here
desc_dev.wIndex = 0;
desc_dev.wLength = 0;

hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_SETUP_TRANSFER;
hc_iocb.handle.ep = epCtrl[i];
hc_iocb.set = &desc_dev;

vos_dev_ioctl(hUsb[i], &hc_iocb);

message("Init complete Port ");
number(i);
message(eol);

}
}
// Signal semaphore is port is configured
if (epCtrl[1]) vos_signal_semaphore(&setupSem1);
if (epCtrl[0]) vos_signal_semaphore(&setupSem0);
++tick;
}
}
while (1);
}


4
OK. Making progress. I split up the code to two threads. One for setup that runs once per second and the other that handles the EP interrupts. This works. I can start with one or two USB devices when powering on. Ideally would I like to detect if  a device is added. The code does that, but it fails to initialise the port where I added say a mouse after the fact and I cannot understand why? Possibly do I not know enough about this environment, so I solicit for help here :)

What happens if I add a mouse to port 0 afterwards is that I see it being detected and configured, but I get a "Port 0 read failure 7" where / apparently is USBHOST_TD_FULL. Why?

Code: [Select]
/*
** Filename: USBHostHID2.c
**
** Adapted from FTDI sample code
**
** Purpose: Act as USB to SPI bridge. passing on keypresses and mouse movements
**
**
** Links/doc:
** http://joshp.no-ip.com:8080/vnc2/#issue2
*/

#include "USBHostHID2.h"

/* FTDI:STP Thread Prototypes */
vos_tcb_t *tcbFIRMWARE;
vos_tcb_t *tcbSETUP;

void firmware();
void setup();

//Driver Handles
VOS_HANDLE hUSBHOST_1; // USB Host Port 1
VOS_HANDLE hUSBHOST_2; // USB Host Port 2
VOS_HANDLE hUART; // UART Interface Driver
#ifdef USE_SPI
VOS_HANDLE hSPI_MASTER; // SPIMaster Interface Driver
#endif

// use our own driver handles to simplify code later
VOS_HANDLE hUsb[2];
int tick = 0;
/* Declaration for IOMUx setup function */
void iomux_setup(void);
//--------------------------- GLOBALS -------------------
// test buffer
char buf[64];
char *eol = "\r\n";
char replybuf[64];

unsigned char i;
unsigned short len;
unsigned short written;
unsigned char status;
unsigned char n, m;
unsigned char ch;
unsigned int replylen;
unsigned char flag;
// GPIO and LEDs
unsigned char leds;

// device handle
usbhost_device_handle_ex ifDev;
// endpoint handles
usbhost_ep_handle_ex epInt[2], epCtrl[2];
// endpoint maxPacketLength values
unsigned char maxPack[2];

// completion semaphore and set semaphore list
vos_semaphore_t semRead;
vos_semaphore_t endpointSem[2];

// Host Controller ioctl request block
usbhost_ioctl_cb_t hc_iocb;
usbhost_ioctl_cb_vid_pid_t hc_ioctVidPid;

// interrupt endpoint transfer descriptor
usbhost_xfer_t xfer[2];

// UART ioctl request block
common_ioctl_cb_t uart_iocb;
#ifdef USE_SPI
// SPI Master ioctl request block
common_ioctl_cb_t spim_iocb;
#endif
// host controller device descriptor
usb_deviceRequest_t desc_dev;

// endpoint information
usbhost_ioctl_cb_ep_info_t epInfo;
//
vos_semaphore_t setupSem;
// ---------------------------------------------------------

// Main code - entry point to firmware
void main(void)
{
// UART Driver configuration context
uart_context_t uartContext;
// USB Host configuration context
usbhost_context_t usbhostContext;

#ifdef USE_SPI
// SPI Master configuration context
spimaster_context_t spimContext;
#endif
// Kernel Initialisation
vos_init(50, VOS_TICK_INTERVAL, VOS_NUMBER_DEVICES);
vos_set_clock_frequency(VOS_48MHZ_CLOCK_FREQUENCY);
vos_set_idle_thread_tcb_size(512);

iomux_setup();

// Initialise UART
#ifdef USE_UART
uartContext.buffer_size = VOS_BUFFER_SIZE_128_BYTES;
uart_init(VOS_DEV_UART,&uartContext);
#endif
//
// SPI
#ifdef USE_SPI
spimContext.buffer_size = VOS_BUFFER_SIZE_128_BYTES;
spimaster_init(VOS_DEV_SPI_MASTER,&spimContext);
#endif

// Initialise USB Host
usbhostContext.if_count = 8;
usbhostContext.ep_count = 16;
usbhostContext.xfer_count = 2;
usbhostContext.iso_xfer_count = 2;
usbhost_init(VOS_DEV_USBHOST_1, VOS_DEV_USBHOST_2, &usbhostContext);

vos_init_semaphore(&setupSem, 0);

//Thread Creation, one for setup, one for interrupts
tcbFIRMWARE = vos_create_thread_ex(21, 4096, firmware, "Application", 0);
tcbFIRMWARE = vos_create_thread_ex(20, 4096, setup, "Setup", 0);
//
vos_gpio_set_port_mode(GPIO_PORT_A, 0xff);  // set all as output for leds
//
vos_start_scheduler();
flag = 0;

main_loop:
goto main_loop;
}

// FTDI:SSP Support Functions

unsigned char usbhost_connect_state(VOS_HANDLE hUSB)
{
unsigned char connectstate = PORT_STATE_DISCONNECTED;
usbhost_ioctl_cb_t hc_iocb;

if (hUSB)
{
hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_GET_CONNECT_STATE;
hc_iocb.get        = &connectstate;
vos_dev_ioctl(hUSB, &hc_iocb);

    // repeat if connected to see if we move to enumerated
if (connectstate == PORT_STATE_CONNECTED)
{
vos_dev_ioctl(hUSB, &hc_iocb);
}
}
return connectstate;
}

void open_drivers(void)
{
/* Code for opening and closing drivers - move to required places in Application Threads */
/* FTDI:SDA Driver Open */
hUSBHOST_1 = vos_dev_open(VOS_DEV_USBHOST_1);
hUSBHOST_2 = vos_dev_open(VOS_DEV_USBHOST_2);
#ifdef USE_UART
hUART = vos_dev_open(VOS_DEV_UART);
#endif
#ifdef USE_SPI
hSPI_MASTER = vos_dev_open(VOS_DEV_SPI_MASTER);
#endif
}

void attach_drivers(void)
{
/* FTDI:SUA Layered Driver Attach Function Calls */
/* FTDI:EUA */
}

void close_drivers(void)
{
vos_dev_close(hUSBHOST_1);
vos_dev_close(hUSBHOST_2);
vos_dev_close(hUART);
#ifdef USE_SPI
vos_dev_close(hSPI_MASTER);
#endif
}

// Helpers
// Write text on UART
void message(char *msg)
{
#ifdef USE_UART
vos_dev_write(hUART, (unsigned char *) msg, strlen(msg), NULL);
#endif
}
// Write number on UART
void number(unsigned char val)
{
#ifdef USE_UART
char letter;
unsigned char nibble;

nibble = (val >> 4) + '0';

if (nibble > '9')
nibble += ('A' - '9' - 1);

vos_dev_write(hUART, &nibble, 1, NULL);
nibble = (val & 15) + '0';

if (nibble > '9')
nibble += ('A' - '9' - 1);

vos_dev_write(hUART, &nibble, 1, NULL);
#endif
}

vos_semaphore_list_t *sem_list;        // pointer to semaphore list
// This is the thread that handles keypresses and mouse movements
void firmware(void)
{
// Wait for the setup sem to finish...
vos_wait_semaphore(&setupSem);
while(1)
{
if (epCtrl[0] || epCtrl[1])
{
sem_list = (vos_semaphore_list_t *) vos_malloc(VOS_SEMAPHORE_LIST_SIZE(2));
sem_list->next = NULL;     // initialise semaphore list
sem_list->siz = 2;         // 2 semaphores (1 for each device endpoint)
sem_list->flags = VOS_SEMAPHORE_FLAGS_WAIT_ANY;

// initialise semaphore
vos_init_semaphore(&endpointSem[0], 0);
vos_init_semaphore(&endpointSem[1], 0);

n = -1;

memset(xfer, 0, sizeof(xfer));

xfer[0].buf = buf;
xfer[0].ep = epInt[0];
xfer[0].s = &endpointSem[0];
// Do not block on completion... we will wait on the sempaphore later
xfer[0].flags = USBHOST_XFER_FLAG_NONBLOCKING | USBHOST_XFER_FLAG_ROUNDING;

xfer[1].buf = buf;
xfer[1].s = &endpointSem[1];
xfer[1].ep = epInt[1];
xfer[1].flags = USBHOST_XFER_FLAG_NONBLOCKING | USBHOST_XFER_FLAG_ROUNDING;

while (1)
{
if(flag == 1) message("hello   ");
// Start or restart each endpoint transfer
if (n != 1 || flag == 1)
{
sem_list->list[0] = &endpointSem[0];
xfer[0].len = maxPack[0];
xfer[0].cond_code = USBHOST_CC_NOTACCESSED;
status = vos_dev_read(hUsb[0], (unsigned char *) &xfer[0], sizeof(usbhost_xfer_t), NULL);

if (status != USBHOST_OK)
{
message("Port 00 Read Failed - code ");
number(status);
message(eol);
//break;
}
flag = 0;
}

if (n != 0 || flag == 1)
{
sem_list->list[1] = &endpointSem[1];
xfer[1].len = maxPack[1];
xfer[1].cond_code = USBHOST_CC_NOTACCESSED;

status = vos_dev_read(hUsb[1], (unsigned char *) &xfer[1], sizeof(usbhost_xfer_t), NULL);

if (status != USBHOST_OK)
{
message("Port 01 Read Failed - code ");
number(status);
message(eol);
//break;
}
flag = 0;
}

// Wait on a key press from either endpoint...
n = vos_wait_semaphore_ex(sem_list);

// Display data received
number(tick++);
message(" Port ");
number(n);
message(" Data: ");

// Display the data from the keyboard...
if (n == 0)
{
//  sem0 has signalled
leds = leds | LED3;
vos_gpio_write_port(GPIO_PORT_A, leds);
replybuf[0] = 0x13;
replybuf[1] = (unsigned char) xfer[0].len;
replylen = 2;
for (i = 0; i < xfer[0].len; i++)
{
number(buf[i]);
ch = buf[i];
replybuf[replylen++] = (ch >> 4); // MSB
replybuf[replylen++] = (ch & 0x0f); // LSB
}
replybuf[replylen++] = 0x14;
#ifdef USE_SPI
vos_dev_write(hSPI_MASTER, (unsigned char *)replybuf, (uint16)replylen, NULL);
#endif
}
else if (n == 1)
{
// sem1 has signalled
leds = led | LED3;
vos_gpio_write_port(GPIO_PORT_A, leds);
replybuf[0] = 0x13;
replybuf[1] = (unsigned char)xfer[1].len;
replylen = 2;
for (i = 0; i < xfer[1].len; i++)
{
number(buf[i]);
ch = buf[i];
replybuf[replylen++] = (ch >> 4); // MSB
replybuf[replylen++] = (ch & 0x0f); // LSB
}
replybuf[replylen++] = 0x14;
#ifdef USE_SPI
vos_dev_write(hSPI_MASTER, (unsigned char *)replybuf, (uint16) replylen, NULL);
#endif
}

message(eol);
}
}
}
}
// Setup the USB ports, then hand off to other thread
void setup(void)
{
int tick = 0;
epInt[0] = NULL;
epCtrl[0] = NULL;
epInt[1] = NULL;
epCtrl[1] = NULL;

open_drivers();
hUsb[0] = hUSBHOST_1;
hUsb[1] = hUSBHOST_2;

#ifdef USE_UART
//uart_iocb.ioctl_code = VOS_IOCTL_COMMON_ENABLE_DMA;
//uart_iocb.set.param = DMA_ACQUIRE_AS_REQUIRED;
//vos_dev_ioctl(hUART, &uart_iocb);

// set baud rate
uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_BAUD_RATE;
uart_iocb.set.uart_baud_rate = UART_BAUD_9600; //UART_BAUD_115200
vos_dev_ioctl(hUART, &uart_iocb);

// set flow control
uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_FLOW_CONTROL;
uart_iocb.set.param = UART_FLOW_RTS_CTS;
vos_dev_ioctl(hUART, &uart_iocb);

// set data bits
uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_DATA_BITS;
uart_iocb.set.param = UART_DATA_BITS_8;
vos_dev_ioctl(hUART, &uart_iocb);

// set stop bits
uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_STOP_BITS;
uart_iocb.set.param = UART_STOP_BITS_1;
vos_dev_ioctl(hUART, &uart_iocb);

// set parity
uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_PARITY;
uart_iocb.set.param = UART_PARITY_NONE;
vos_dev_ioctl(hUART, &uart_iocb);
#endif
#ifdef USE_SPI
// set clock phase
spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_SCK_CPHA;
spim_iocb.set.param = SPI_MASTER_SCK_CPHA_0;
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
// set clock polarity
spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_SCK_CPOL;
spim_iocb.set.param = SPI_MASTER_SCK_CPOL_0;
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
// set data order
spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_DATA_ORDER;
spim_iocb.set.param = SPI_MASTER_DATA_ORDER_MSB;
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
// enable DMA
spim_iocb.ioctl_code = VOS_IOCTL_COMMON_ENABLE_DMA;
spim_iocb.set = DMA_ACQUIRE_AND_RETAIN;
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
// set clock rate
spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_SET_SCK_FREQUENCY;
spim_iocb.set.spi_master_sck_freq = 300000; // /10
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
// set auto toggle
spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_AUTO_TOGGLE_SS;
spim_iocb.set.param = SPI_MASTER_SS_AUTO_TOGGLE_ENABLE_SS_0;
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
#endif
message("Starting...\r\n");
#ifdef USE_SPI
message("With SPI...\r\n");
#endif
do
{
vos_delay_msecs(1000);
// check if USB port i is configured already
for (i = 0; i < 2; i++)
{
if (epCtrl[i] == NULL)
{
// user ioctl to see if selected USB port available
if (usbhost_connect_state(hUsb[i]) == PORT_STATE_ENUMERATED)
{
message("Enumeration complete Port ");
number(i);
message(eol);
if(i==0) leds = leds | LED1;
else leds = leds | LED2;
vos_gpio_write_port(GPIO_PORT_A, leds);

// user ioctl to find first hub device
hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_NEXT_HANDLE;
// find first device interface
hc_iocb.handle.dif = NULL;
// hc_iocb.set = &hc_ioctVidPid;
hc_iocb.get = &ifDev;
status = vos_dev_ioctl(hUsb[i], &hc_iocb);

if (status != USBHOST_OK)
{
message("No Device Found - code ");
number(status);
message(eol);
break;
}

// user ioctl to find control endpoint on this device
hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_CONTROL_ENDPOINT_HANDLE;
hc_iocb.handle.dif = ifDev;
hc_iocb.get = &epCtrl[i];

status = vos_dev_ioctl(hUsb[i], &hc_iocb);

if (status != USBHOST_OK)
{
message("No Control Endpoint Found - code ");
number(status);
message(eol);
break;
}

// user ioctl to find first interrupt endpoint on this device
hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_INT_IN_ENDPOINT_HANDLE;
hc_iocb.handle.dif = ifDev;
hc_iocb.get = &epInt[i];
status = vos_dev_ioctl(hUsb[i], &hc_iocb);

if (status != USBHOST_OK)
{
message("No interrupt Endpoint Found - code ");
number(status);
message(eol);
break;
}

// user ioctl to find interrupt endpoint on this device
hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_ENDPOINT_INFO;
hc_iocb.handle.ep = epInt[i];
hc_iocb.get = &epInfo;

status = vos_dev_ioctl(hUsb[i], &hc_iocb);

if (status != USBHOST_OK)
{
message("Interrupt Endpoint Info Not Found - code ");
number(status);
message(eol);
break;
}

maxPack[i] = epInfo.max_size;

desc_dev.bmRequestType = USB_BMREQUESTTYPE_HOST_TO_DEV |
USB_BMREQUESTTYPE_CLASS |
USB_BMREQUESTTYPE_INTERFACE;
desc_dev.bRequest = 0x0a; // USB_HID_REQUEST_CODE_SET_IDLE
desc_dev.wValue = 0; // Repeat rate here
desc_dev.wIndex = 0;
desc_dev.wLength = 0;

hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_SETUP_TRANSFER;
hc_iocb.handle.ep = epCtrl[i];
hc_iocb.set = &desc_dev;

vos_dev_ioctl(hUsb[i], &hc_iocb);

message("Init complete Port ");
number(i);
message(eol);
flag = 1; // Signal to other thread
}
}
if (epCtrl[0] && epCtrl[1]) vos_signal_semaphore(&setupSem);
if ((epCtrl[0] || epCtrl[1]) && tick > 5) vos_signal_semaphore(&setupSem);
++tick;
}
}
while (1);
}



5
Well, in this case it was the same key, but removing UART fixed it. It now works as advertised.

6
Removing all the UART stuff led to a marked improvement.

Next task is to adapt the code so that it does not require both USB ports to be connected.

7
Code: [Select]
/*
** Filename: USBHostHID2.c
**
** Automatically created by Application Wizard 1.4.2
**
** Part of solution USBHostHID2 in project USBHostHID2
**
** Comments:
**
** Important: Sections between markers "FTDI:S*" and "FTDI:E*" will be overwritten by
** the Application Wizard
*/

#include "USBHostHID2.h"
//#define USE_SPI

/* FTDI:STP Thread Prototypes */
vos_tcb_t *tcbFIRMWARE;

void firmware();
/* FTDI:ETP */

/* FTDI:SDH Driver Handles */
VOS_HANDLE hUSBHOST_1; // USB Host Port 1
VOS_HANDLE hUSBHOST_2; // USB Host Port 2
VOS_HANDLE hUART; // UART Interface Driver
#ifdef USE_SPI
VOS_HANDLE hSPI_MASTER; // SPIMaster Interface Driver
#endif
/* FTDI:EDH */
// use our own driver handles to simplify code later
VOS_HANDLE hUsb[2];

/* Declaration for IOMUx setup function */
void iomux_setup(void);

/* Main code - entry point to firmware */
void main(void)
{
/* FTDI:SDD Driver Declarations */
// UART Driver configuration context
uart_context_t uartContext;
// USB Host configuration context
usbhost_context_t usbhostContext;
/* FTDI:EDD */
#ifdef USE_SPI
// SPI Master configuration context
spimaster_context_t spimContext;
#endif
/* FTDI:SKI Kernel Initialisation */
vos_init(50, VOS_TICK_INTERVAL, VOS_NUMBER_DEVICES);
vos_set_clock_frequency(VOS_48MHZ_CLOCK_FREQUENCY);
vos_set_idle_thread_tcb_size(512);
/* FTDI:EKI */

iomux_setup();

/* FTDI:SDI Driver Initialisation */
// Initialise UART
uartContext.buffer_size = VOS_BUFFER_SIZE_128_BYTES;
uart_init(VOS_DEV_UART,&uartContext);
//
// SPI
#ifdef USE_SPI
spimContext.buffer_size = VOS_BUFFER_SIZE_128_BYTES;
spimaster_init(VOS_DEV_SPI_MASTER,&spimContext);
#endif

// Initialise USB Host
usbhostContext.if_count = 8;
usbhostContext.ep_count = 16;
usbhostContext.xfer_count = 2;
usbhostContext.iso_xfer_count = 2;
usbhost_init(VOS_DEV_USBHOST_1, VOS_DEV_USBHOST_2, &usbhostContext);
/* FTDI:EDI */

/* FTDI:SCT Thread Creation */
tcbFIRMWARE = vos_create_thread_ex(20, 4096, firmware, "Application", 0);
/* FTDI:ECT */

vos_start_scheduler();

main_loop:
goto main_loop;
}

/* FTDI:SSP Support Functions */

unsigned char usbhost_connect_state(VOS_HANDLE hUSB)
{
unsigned char connectstate = PORT_STATE_DISCONNECTED;
usbhost_ioctl_cb_t hc_iocb;

if (hUSB)
{
hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_GET_CONNECT_STATE;
hc_iocb.get        = &connectstate;
vos_dev_ioctl(hUSB, &hc_iocb);

    // repeat if connected to see if we move to enumerated
if (connectstate == PORT_STATE_CONNECTED)
{
vos_dev_ioctl(hUSB, &hc_iocb);
}
}
return connectstate;
}

/* FTDI:ESP */

void open_drivers(void)
{
/* Code for opening and closing drivers - move to required places in Application Threads */
/* FTDI:SDA Driver Open */
hUSBHOST_1 = vos_dev_open(VOS_DEV_USBHOST_1);
hUSBHOST_2 = vos_dev_open(VOS_DEV_USBHOST_2);
hUART = vos_dev_open(VOS_DEV_UART);
#ifdef USE_SPI
hSPI_MASTER = vos_dev_open(VOS_DEV_SPI_MASTER);
#endif
/* FTDI:EDA */
}

void attach_drivers(void)
{
/* FTDI:SUA Layered Driver Attach Function Calls */
/* FTDI:EUA */
}

void close_drivers(void)
{
/* FTDI:SDB Driver Close */
vos_dev_close(hUSBHOST_1);
vos_dev_close(hUSBHOST_2);
vos_dev_close(hUART);
#ifdef USE_SPI
vos_dev_close(hSPI_MASTER);
#endif
/* FTDI:EDB */
}

/* Application Threads */

void message(char *msg)
{
vos_dev_write(hUART, (unsigned char *) msg, strlen(msg), NULL);
}

void number(unsigned char val)
{
char letter;
unsigned char nibble;

nibble = (val >> 4) + '0';

if (nibble > '9')
nibble += ('A' - '9' - 1);

vos_dev_write(hUART, &nibble, 1, NULL);
nibble = (val & 15) + '0';

if (nibble > '9')
nibble += ('A' - '9' - 1);

vos_dev_write(hUART, &nibble, 1, NULL);
}

void spinumber(unsigned char val)
{
#ifdef USE_SPI
char letter;
unsigned char nibble;

nibble = (val >> 4) + '0';

if (nibble > '9')
nibble += ('A' - '9' - 1);

vos_dev_write(hSPI_MASTER, &nibble, 1, NULL);
nibble = (val & 15) + '0';

if (nibble > '9')
nibble += ('A' - '9' - 1);

vos_dev_write(hSPI_MASTER, &nibble, 1, NULL);
#endif
}

vos_semaphore_list_t *sem_list;        // pointer to semaphore list

void firmware(void)
{
// test buffer
char buf[64];
char *eol = "\r\n";
char replybuf[64];

unsigned char i;
unsigned short len;
unsigned short written;
unsigned char status;
unsigned char n, m;
unsigned char ch;
unsigned int replylen;

// device handle
usbhost_device_handle_ex ifDev;
// endpoint handles
usbhost_ep_handle_ex epInt[2], epCtrl[2];
// endpoint maxPacketLength values
unsigned char maxPack[2];

// completion semaphore and set semaphore list
vos_semaphore_t semRead;
vos_semaphore_t endpointSem[2];

// Host Controller ioctl request block
usbhost_ioctl_cb_t hc_iocb;
usbhost_ioctl_cb_vid_pid_t hc_ioctVidPid;

// interrupt endpoint transfer descriptor
usbhost_xfer_t xfer[2];

// UART ioctl request block
common_ioctl_cb_t uart_iocb;
#ifdef USE_SPI
// SPI Master ioctl request block
common_ioctl_cb_t spim_iocb;
#endif

// host controller device descriptor
usb_deviceRequest_t desc_dev;

// endpoint information
usbhost_ioctl_cb_ep_info_t epInfo;

epInt[0] = NULL;
epCtrl[0] = NULL;
epInt[1] = NULL;
epCtrl[1] = NULL;

open_drivers();
hUsb[0] = hUSBHOST_1;
hUsb[1] = hUSBHOST_2;

//uart_iocb.ioctl_code = VOS_IOCTL_COMMON_ENABLE_DMA;
//uart_iocb.set.param = DMA_ACQUIRE_AS_REQUIRED;
//vos_dev_ioctl(hUART, &uart_iocb);

// set baud rate
uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_BAUD_RATE;
uart_iocb.set.uart_baud_rate = UART_BAUD_115200;
vos_dev_ioctl(hUART, &uart_iocb);

// set flow control
uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_FLOW_CONTROL;
uart_iocb.set.param = UART_FLOW_RTS_CTS;
vos_dev_ioctl(hUART, &uart_iocb);

// set data bits
uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_DATA_BITS;
uart_iocb.set.param = UART_DATA_BITS_8;
vos_dev_ioctl(hUART, &uart_iocb);

// set stop bits
uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_STOP_BITS;
uart_iocb.set.param = UART_STOP_BITS_1;
vos_dev_ioctl(hUART, &uart_iocb);

// set parity
uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_PARITY;
uart_iocb.set.param = UART_PARITY_NONE;
vos_dev_ioctl(hUART, &uart_iocb);
#ifdef USE_SPI
// set clock phase
spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_SCK_CPHA;
spim_iocb.set.param = SPI_MASTER_SCK_CPHA_0;
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
// set clock polarity
spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_SCK_CPOL;
spim_iocb.set.param = SPI_MASTER_SCK_CPOL_0;
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
// set data order
spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_DATA_ORDER;
spim_iocb.set.param = SPI_MASTER_DATA_ORDER_MSB;
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
// enable DMA
spim_iocb.ioctl_code = VOS_IOCTL_COMMON_ENABLE_DMA;
spim_iocb.set = DMA_ACQUIRE_AND_RETAIN;
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
// set clock rate
spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_SET_SCK_FREQUENCY;
spim_iocb.set.spi_master_sck_freq = 300000; // /10
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
// set auto toggle
spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_AUTO_TOGGLE_SS;
spim_iocb.set.param = SPI_MASTER_SS_AUTO_TOGGLE_ENABLE_SS_0;
vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
#endif
message("Starting...\r\n");
#ifdef USE_SPI
message("With SPI...\r\n");
//vos_dev_write(hSPI_MASTER, "With SPI...\r\n", 13, NULL);
#endif
do
{
vos_delay_msecs(100);

// check if USB port 1 is configured already
for (i = 0; i < 2; i++)
{
if (epCtrl[i] == NULL)
{
// user ioctl to see if selected USB port available
if (usbhost_connect_state(hUsb[i]) == PORT_STATE_ENUMERATED)
{
message("Enumeration complete Port ");
number(i);
message(eol);

// user ioctl to find first hub device
hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_NEXT_HANDLE;
// find first device interface
hc_iocb.handle.dif = NULL;
// hc_iocb.set = &hc_ioctVidPid;
hc_iocb.get = &ifDev;
status = vos_dev_ioctl(hUsb[i], &hc_iocb);

if (status != USBHOST_OK)
{
message("No Device Found - code ");
number(status);
message(eol);
break;
}

// user ioctl to find control endpoint on this device
hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_CONTROL_ENDPOINT_HANDLE;
hc_iocb.handle.dif = ifDev;
hc_iocb.get = &epCtrl[i];

status = vos_dev_ioctl(hUsb[i], &hc_iocb);

if (status != USBHOST_OK)
{
message("No Control Endpoint Found - code ");
number(status);
message(eol);
break;
}

// user ioctl to find first interrupt endpoint on this device
hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_INT_IN_ENDPOINT_HANDLE;
hc_iocb.handle.dif = ifDev;
hc_iocb.get = &epInt[i];
status = vos_dev_ioctl(hUsb[i], &hc_iocb);

if (status != USBHOST_OK)
{
message("No interrupt Endpoint Found - code ");
number(status);
message(eol);
break;
}

// user ioctl to find interrupt endpoint on this device
hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_ENDPOINT_INFO;
hc_iocb.handle.ep = epInt[i];
hc_iocb.get = &epInfo;

status = vos_dev_ioctl(hUsb[i], &hc_iocb);

if (status != USBHOST_OK)
{
message("Interrupt Endpoint Info Not Found - code ");
number(status);
message(eol);
break;
}

maxPack[i] = epInfo.max_size;

desc_dev.bmRequestType = USB_BMREQUESTTYPE_HOST_TO_DEV |
USB_BMREQUESTTYPE_CLASS |
USB_BMREQUESTTYPE_INTERFACE;
desc_dev.bRequest = 0x0a; // USB_HID_REQUEST_CODE_SET_IDLE
desc_dev.wValue = 0; // Repeat rate here
desc_dev.wIndex = 0;
desc_dev.wLength = 0;

hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_SETUP_TRANSFER;
hc_iocb.handle.ep = epCtrl[i];
hc_iocb.set = &desc_dev;

vos_dev_ioctl(hUsb[i], &hc_iocb);


message("Init complete Port ");
number(i);
message(eol);
}
}
}

if (epCtrl[0] && epCtrl[1])
{
sem_list = (vos_semaphore_list_t *) vos_malloc(VOS_SEMAPHORE_LIST_SIZE(2));
sem_list->next = NULL;     // initialise semaphore list
sem_list->siz = 2;         // 2 semaphores (1 for each device endpoint)
sem_list->flags = VOS_SEMAPHORE_FLAGS_WAIT_ANY;

// initialise semaphore
vos_init_semaphore(&endpointSem[0], 0);
vos_init_semaphore(&endpointSem[1], 0);

n = -1;

memset(xfer, 0, sizeof(xfer));

xfer[0].buf = buf;
xfer[0].ep = epInt[0];
xfer[0].s = &endpointSem[0];
// Do not block on completion... we will wait on the sempaphore later
xfer[0].flags = USBHOST_XFER_FLAG_NONBLOCKING | USBHOST_XFER_FLAG_ROUNDING;

xfer[1].buf = buf;
xfer[1].s = &endpointSem[1];
xfer[1].ep = epInt[1];
xfer[1].flags = USBHOST_XFER_FLAG_NONBLOCKING | USBHOST_XFER_FLAG_ROUNDING;

while (1)
{
// Start or restart each endpoint transfer
if (n != 1)
{
sem_list->list[0] = &endpointSem[0];
xfer[0].len = maxPack[0];
xfer[0].cond_code = USBHOST_CC_NOTACCESSED;
status = vos_dev_read(hUsb[0], (unsigned char *) &xfer[0], sizeof(usbhost_xfer_t), NULL);

if (status != USBHOST_OK)
{
message("Port 00 Read Failed - code ");
number(status);
message(eol);
break;
}
}

if (n != 0)
{
sem_list->list[1] = &endpointSem[1];
xfer[1].len = maxPack[1];
xfer[1].cond_code = USBHOST_CC_NOTACCESSED;

status = vos_dev_read(hUsb[1], (unsigned char *) &xfer[1], sizeof(usbhost_xfer_t), NULL);

if (status != USBHOST_OK)
{
message("Port 01 Read Failed - code ");
number(status);
message(eol);
break;
}
}

// Wait on a key press from either endpoint...
n = vos_wait_semaphore_ex(sem_list);

// Display data received
message("Port ");
number(n);
message(" Data: ");

// Display the data from the keyboard...
if (n == 0)
{
//  sem0 has signalled
replybuf[0] = 0x13;
replybuf[1] = (unsigned char) xfer[0].len;
replylen = 2;
for (i = 0; i < xfer[0].len; i++)
{
number(buf[i]);
ch = buf[i];
replybuf[replylen++] = (ch >> 4); // MSB
replybuf[replylen++] = (ch & 0x0f); // LSB
}
replybuf[replylen++] = 0x14;
#ifdef USE_SPI
vos_dev_write(hSPI_MASTER, (unsigned char *)replybuf, (uint16)replylen, NULL);
#endif
}
else if (n == 1)
{
// sem1 has signalled
replybuf[0] = 0x13;
replybuf[1] = (unsigned char)xfer[1].len;
replylen = 2;
for (i = 0; i < xfer[1].len; i++)
{
number(buf[i]);
ch = buf[i];
replybuf[replylen++] = (ch >> 4); // MSB
replybuf[replylen++] = (ch & 0x0f); // LSB
}
replybuf[replylen++] = 0x14;
#ifdef USE_SPI
vos_dev_write(hSPI_MASTER, (unsigned char *)replybuf, (uint16) replylen, NULL);
#endif
}

message(eol);
}
}
}
while (1);
}


8
Hi!

I am trying to adapt USBHostHID2.c for ose as an USB to SPI bridge and have run into problems. Those problems appear even if I have no SPI defined. The problems are:
1. When typing fast, reports from the keyboard go missing or arrive in the wrong order. Ie instead of one press one release, I get two presses followed by two releases.
2. The unit hangs hard after some time. This seems to happen if you type really fast on the keyboard or move the mouse a lot.

I have attached the USBHostHID2.* files, with my additions. This is on the 32-pin VNC2.

Code: [Select]
/*
** Filename: USBHostHID2_iomux.c
**
** Automatically created by Application Wizard 1.4.2
**
** Part of solution USBHostHID2 in project USBHostHID2
**
** Comments:
**
** Important: Sections between markers "FTDI:S*" and "FTDI:E*" will be overwritten by
** the Application Wizard
*/
#include "vos.h"

void iomux_setup(void)
{
/* FTDI:SIO IOMux Functions */
unsigned char packageType;

packageType = vos_get_package_type();
if (packageType == VINCULUM_II_32_PIN)
{
// Debugger to pin 11 as Bi-Directional.
vos_iomux_define_bidi(199, IOMUX_IN_DEBUGGER, IOMUX_OUT_DEBUGGER);
// GPIO_Port_A_1 to pin 12 as Input.
vos_iomux_define_input(12, IOMUX_IN_GPIO_PORT_A_1);
// GPIO_Port_A_2 to pin 14 as Input.
vos_iomux_define_input(14, IOMUX_IN_GPIO_PORT_A_2);
// GPIO_Port_A_3 to pin 15 as Input.
vos_iomux_define_input(15, IOMUX_IN_GPIO_PORT_A_3);
// UART_TXD to pin 23 as Output.
vos_iomux_define_output(23, IOMUX_OUT_UART_TXD);
// UART_RXD to pin 24 as Input.
vos_iomux_define_input(24, IOMUX_IN_UART_RXD);
// UART_RTS_N to pin 25 as Output.
vos_iomux_define_output(25, IOMUX_OUT_UART_RTS_N);
// UART_CTS_N to pin 26 as Input.
vos_iomux_define_input(26, IOMUX_IN_UART_CTS_N);
// SPI_Slave_0_CLK to pin 29 as Input.
//vos_iomux_define_input(29, IOMUX_IN_SPI_SLAVE_0_CLK);
// SPI_Slave_0_MOSI to pin 30 as Input.
//vos_iomux_define_input(30, IOMUX_IN_SPI_SLAVE_0_MOSI);
// SPI_Slave_0_MISO to pin 31 as Output.
//vos_iomux_define_output(31, IOMUX_OUT_SPI_SLAVE_0_MISO);
// SPI_Slave_0_CS to pin 32 as Input.
//vos_iomux_define_input(32, IOMUX_IN_SPI_SLAVE_0_CS);
//
// SPI Master
//
// SPI_Slave_0_CLK to pin 29 as output. IO8 ie J1 11
vos_iomux_define_output(29, IOMUX_OUT_SPI_MASTER_CLK);
// SPI_Slave_0_MOSI to pin 30 as output. IO 9, ie J1-12
vos_iomux_define_output(30, IOMUX_OUT_SPI_MASTER_MOSI);
// SPI_Slave_0_MISO to pin 31 as input. IO 10 ie J2-12
vos_iomux_define_input(31, IOMUX_IN_SPI_MASTER_MISO);
// SPI_Slave_0_CS to pin 32 as output. IO 11 ie J2-11
vos_iomux_define_output(32, IOMUX_OUT_SPI_MASTER_CS_0);
}
if (packageType == VINCULUM_II_48_PIN)
{
// Debugger to pin 11 as Bi-Directional.
vos_iomux_define_bidi(199, IOMUX_IN_DEBUGGER, IOMUX_OUT_DEBUGGER);
// PWM_1 to pin 12 as Output.
vos_iomux_define_output(12, IOMUX_OUT_PWM_1);
// PWM_2 to pin 13 as Output.
vos_iomux_define_output(13, IOMUX_OUT_PWM_2);
// PWM_3 to pin 14 as Output.
vos_iomux_define_output(14, IOMUX_OUT_PWM_3);
// UART_RI to pin 46 as Input.
vos_iomux_define_input(46, IOMUX_IN_UART_RI);
// UART_DCD to pin 45 as Input.
vos_iomux_define_input(45, IOMUX_IN_UART_DCD);
// GPIO_Port_A_4 to pin 48 as Input.
vos_iomux_define_input(48, IOMUX_IN_GPIO_PORT_A_4);
// UART_TXD to pin 31 as Output.
vos_iomux_define_output(31, IOMUX_OUT_UART_TXD);
// UART_RXD to pin 32 as Input.
vos_iomux_define_input(32, IOMUX_IN_UART_RXD);
// UART_RTS_N to pin 33 as Output.
vos_iomux_define_output(33, IOMUX_OUT_UART_RTS_N);
// UART_CTS_N to pin 34 as Input.
vos_iomux_define_input(34, IOMUX_IN_UART_CTS_N);
// UART_DTR_N to pin 35 as Output.
vos_iomux_define_output(35, IOMUX_OUT_UART_DTR_N);
// UART_DSR_N to pin 36 as Input.
vos_iomux_define_input(36, IOMUX_IN_UART_DSR_N);
// UART_DCD to pin 37 as Input.
vos_iomux_define_input(37, IOMUX_IN_UART_DCD);
// UART_RI to pin 38 as Input.
vos_iomux_define_input(38, IOMUX_IN_UART_RI);
// UART_TX_Active to pin 41 as Output.
vos_iomux_define_output(41, IOMUX_OUT_UART_TX_ACTIVE);
// SPI_Slave_0_CLK to pin 15 as Input.
vos_iomux_define_input(15, IOMUX_IN_SPI_SLAVE_0_CLK);
// SPI_Slave_0_MOSI to pin 16 as Input.
vos_iomux_define_input(16, IOMUX_IN_SPI_SLAVE_0_MOSI);
// SPI_Slave_0_MISO to pin 18 as Output.
vos_iomux_define_output(18, IOMUX_OUT_SPI_SLAVE_0_MISO);
// SPI_Slave_0_CS to pin 19 as Input.
vos_iomux_define_input(19, IOMUX_IN_SPI_SLAVE_0_CS);
// SPI_Master_CLK to pin 20 as Output.
vos_iomux_define_output(20, IOMUX_OUT_SPI_MASTER_CLK);
// SPI_Master_MOSI to pin 21 as Output.
vos_iomux_define_output(21, IOMUX_OUT_SPI_MASTER_MOSI);
// SPI_Master_MISO to pin 22 as Input.
vos_iomux_define_input(22, IOMUX_IN_SPI_MASTER_MISO);
// SPI_Master_CS_0 to pin 23 as Output.
vos_iomux_define_output(23, IOMUX_OUT_SPI_MASTER_CS_0);

}
if (packageType == VINCULUM_II_64_PIN)
{
// Debugger to pin 11 as Bi-Directional.
vos_iomux_define_bidi(199, IOMUX_IN_DEBUGGER, IOMUX_OUT_DEBUGGER);
// FIFO_Data_0 to pin 15 as Bi-Directional.
vos_iomux_define_bidi(15, IOMUX_IN_FIFO_DATA_0, IOMUX_OUT_FIFO_DATA_0);
// FIFO_Data_1 to pin 16 as Bi-Directional.
vos_iomux_define_bidi(16, IOMUX_IN_FIFO_DATA_1, IOMUX_OUT_FIFO_DATA_1);
// FIFO_Data_2 to pin 17 as Bi-Directional.
vos_iomux_define_bidi(17, IOMUX_IN_FIFO_DATA_2, IOMUX_OUT_FIFO_DATA_2);
// FIFO_Data_3 to pin 18 as Bi-Directional.
vos_iomux_define_bidi(18, IOMUX_IN_FIFO_DATA_3, IOMUX_OUT_FIFO_DATA_3);
// FIFO_Data_4 to pin 19 as Bi-Directional.
vos_iomux_define_bidi(19, IOMUX_IN_FIFO_DATA_4, IOMUX_OUT_FIFO_DATA_4);
// FIFO_Data_5 to pin 20 as Bi-Directional.
vos_iomux_define_bidi(20, IOMUX_IN_FIFO_DATA_5, IOMUX_OUT_FIFO_DATA_5);
// FIFO_Data_6 to pin 22 as Bi-Directional.
vos_iomux_define_bidi(22, IOMUX_IN_FIFO_DATA_6, IOMUX_OUT_FIFO_DATA_6);
// FIFO_Data_7 to pin 23 as Bi-Directional.
vos_iomux_define_bidi(23, IOMUX_IN_FIFO_DATA_7, IOMUX_OUT_FIFO_DATA_7);
// FIFO_RXF_N to pin 24 as Output.
vos_iomux_define_output(24, IOMUX_OUT_FIFO_RXF_N);
// FIFO_TXE_N to pin 25 as Output.
vos_iomux_define_output(25, IOMUX_OUT_FIFO_TXE_N);
// FIFO_RD_N to pin 26 as Input.
vos_iomux_define_input(26, IOMUX_IN_FIFO_RD_N);
// FIFO_WR_N to pin 27 as Input.
vos_iomux_define_input(27, IOMUX_IN_FIFO_WR_N);
// FIFO_OE_N to pin 28 as Input.
vos_iomux_define_input(28, IOMUX_IN_FIFO_OE_N);
// UART_DSR_N to pin 29 as Input.
vos_iomux_define_input(29, IOMUX_IN_UART_DSR_N);
// UART_DCD to pin 31 as Input.
vos_iomux_define_input(31, IOMUX_IN_UART_DCD);
// UART_RI to pin 32 as Input.
vos_iomux_define_input(32, IOMUX_IN_UART_RI);
// UART_TXD to pin 39 as Output.
vos_iomux_define_output(39, IOMUX_OUT_UART_TXD);
// UART_RXD to pin 40 as Input.
vos_iomux_define_input(40, IOMUX_IN_UART_RXD);
// UART_RTS_N to pin 41 as Output.
vos_iomux_define_output(41, IOMUX_OUT_UART_RTS_N);
// UART_CTS_N to pin 42 as Input.
vos_iomux_define_input(42, IOMUX_IN_UART_CTS_N);
// UART_DTR_N to pin 43 as Output.
vos_iomux_define_output(43, IOMUX_OUT_UART_DTR_N);
// UART_DSR_N to pin 44 as Input.
vos_iomux_define_input(44, IOMUX_IN_UART_DSR_N);
// UART_DCD to pin 45 as Input.
vos_iomux_define_input(45, IOMUX_IN_UART_DCD);
// UART_RI to pin 46 as Input.
vos_iomux_define_input(46, IOMUX_IN_UART_RI);
// UART_TX_Active to pin 47 as Output.
vos_iomux_define_output(47, IOMUX_OUT_UART_TX_ACTIVE);
// SPI_Slave_0_CLK to pin 51 as Input.
vos_iomux_define_input(51, IOMUX_IN_SPI_SLAVE_0_CLK);
// SPI_Slave_0_MOSI to pin 52 as Input.
vos_iomux_define_input(52, IOMUX_IN_SPI_SLAVE_0_MOSI);
// SPI_Slave_0_MISO to pin 55 as Output.
vos_iomux_define_output(55, IOMUX_OUT_SPI_SLAVE_0_MISO);
// SPI_Slave_0_CS to pin 56 as Input.
vos_iomux_define_input(56, IOMUX_IN_SPI_SLAVE_0_CS);
// SPI_Slave_1_CLK to pin 57 as Input.
vos_iomux_define_input(57, IOMUX_IN_SPI_SLAVE_1_CLK);
// SPI_Slave_1_MOSI to pin 58 as Input.
vos_iomux_define_input(58, IOMUX_IN_SPI_SLAVE_1_MOSI);
// SPI_Slave_1_MISO to pin 59 as Output.
vos_iomux_define_output(59, IOMUX_OUT_SPI_SLAVE_1_MISO);
// SPI_Slave_1_CS to pin 60 as Input.
vos_iomux_define_input(60, IOMUX_IN_SPI_SLAVE_1_CS);
// SPI_Master_CLK to pin 61 as Output.
vos_iomux_define_output(61, IOMUX_OUT_SPI_MASTER_CLK);
// SPI_Master_MOSI to pin 62 as Output.
vos_iomux_define_output(62, IOMUX_OUT_SPI_MASTER_MOSI);
// SPI_Master_MISO to pin 63 as Input.
vos_iomux_define_input(63, IOMUX_IN_SPI_MASTER_MISO);
// SPI_Master_CS_0 to pin 64 as Output.
vos_iomux_define_output(64, IOMUX_OUT_SPI_MASTER_CS_0);

}

/* FTDI:EIO */
}


Code: [Select]
/*
** Filename: USBHostHID2.h
**
** Automatically created by Application Wizard 1.4.2
**
** Part of solution USBHostHID2 in project USBHostHID2
**
** Comments:
**
** Important: Sections between markers "FTDI:S*" and "FTDI:E*" will be overwritten by
** the Application Wizard
*/

#ifndef _USBHostHID2_H_
#define _USBHostHID2_H_

#include "vos.h"

//#define USE_SPI 1

/* FTDI:SHF Header Files */
#include "USB.h"
#include "USBHost.h"
#include "ioctl.h"
#include "UART.h"
#include "string.h"
#include "errno.h"
/* FTDI:EHF */

/* FTDI:SDC Driver Constants */
#define VOS_DEV_USBHOST_1 0
#define VOS_DEV_USBHOST_2 1
#define VOS_DEV_UART 2



#ifdef USE_SPI
#include "SPIMaster.h"
#define VOS_DEV_SPI_MASTER 3
#define VOS_NUMBER_DEVICES 4
#else
#define VOS_NUMBER_DEVICES 3
#endif
/* FTDI:EDC */

/* FTDI:SXH Externs */
/* FTDI:EXH */

#endif                                 /* _USBHostHID2_H_ */

9
OK. Good to know. Yes, it compiles correctly, but it is confusing :)

10
Noted this: I am playing with the USBHostHID2 sample as it will probably do exctly what we need if we adapt it to SPI. Now, having USART as well is handy for troubleshooting, so I did this in the USBHostHID2.h file:

Code: [Select]
#ifndef _USBHostHID2_H_
#define _USBHostHID2_H_

#include "vos.h"

#define USE_SPI 1

/* FTDI:SHF Header Files */
#include "USB.h"
#include "USBHost.h"
#include "ioctl.h"
#include "UART.h"
#include "string.h"
#include "errno.h"
/* FTDI:EHF */

/* FTDI:SDC Driver Constants */
#define VOS_DEV_USBHOST_1 0
#define VOS_DEV_USBHOST_2 1
#define VOS_DEV_UART 2



#ifdef USE_SPI
#include "SPIMaster.h"
#define VOS_DEV_SPI_MASTER 3
#define VOS_NUMBER_DEVICES 4
#else
#define VOS_NUMBER_DEVICES 3
#endif
/* FTDI:EDC */

/* FTDI:SXH Externs */
/* FTDI:EXH */

#endif

and in the *.c file:

Code: [Select]
/* FTDI:SDH Driver Handles */
VOS_HANDLE hUSBHOST_1; // USB Host Port 1
VOS_HANDLE hUSBHOST_2; // USB Host Port 2
VOS_HANDLE hUART; // UART Interface Driver
#ifdef USE_SPI
VOS_HANDLE hSPI_MASTER; // SPIMaster Interface Driver
#endif


etc. Problem is that the IDE grays out the "VOS_HANDLE hSPI_MASTER" even if USE_SPI is defined. The code is clearly included though, ie:

Code: [Select]
message("Starting...\r\n");
#ifdef USE_SPI
message("With SPI...\r\n");
vos_dev_write(hSPI_MASTER, "With SPI...\r\n", 13, NULL);
#endif

This is the latest tooldchain downloaded from your website.

11
Discussion - Hardware / Connecting unused pins on the VNC1L?
« on: October 18, 2020, 11:33:59 AM »
Simple question: If I use a VNC1L as an USB to SPI bridge, do I need to connect the unused pins or can they be left floating? I noticed that on the VDIP-1 board there are 100k pullups on ADBUS 0..7 and ACBUS 0..4, but not on BDBUS 0..7 and BCBUS 0..3.

12
Thanks! I will look into it. FWIW, I think I have it sorted with the VNC1L though.

The VNC2-32L1C looks tempting though.. How different is it from the VNC1 as an USB to SPI host?

13
I have a design for an universal keyboard controller for a special type of equipment that use a proprietary protocol. The design is based on a PI24 microcontroller. Unfortunately does that PIC only have one USB port and the microchip libraries lack support for hubs so I thought I'd investigate using a VNC1L as I already had one from another project. The proprietary protocol part is done as is PS/2 input for both Keyboard and mouse.

I am interfacing the VNC1L through SPI and I run it at maximum speed. The docs are sketchy, but I found some examples, brief ones in the internet, but I am wondering if I am going about things the wrong way as this implementation is far from ideal, ie:

You issue an "SSU $A101000100000800"  and then loop polling "SSU $210A003D00000000" where 3D is the desired poll speed.

Sometimes, out of the blue the VNC1L will return "Command failed" in which case I have to reissue "SSU $A101000100000800" and then continue polling.

My problem is that this polling eats a lot of cpu cycles that are better needed elsewhere. Is there a more elegant way to do this with a VNC1L or with another chip?

Pages: [1]