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

Author Topic: Adapting USBHostHID2 - Support one or two devices. Detect insertion.  (Read 82 times)

AndersG

  • Newbie
  • *
  • Posts: 11
    • View Profile

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);
}


Logged
/AndersG

AndersG

  • Newbie
  • *
  • Posts: 11
    • View Profile
Re: Adapting USBHostHID2 - Support one or two devices. Detect insertion.
« Reply #1 on: November 21, 2020, 02:36:49 PM »

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);
}

Logged
/AndersG

FTDI Community

  • Administrator
  • Hero Member
  • *****
  • Posts: 507
    • View Profile
Re: Adapting USBHostHID2 - Support one or two devices. Detect insertion.
« Reply #2 on: November 23, 2020, 10:16:32 PM »

Hello,

There was nothing wrong with what you are doing except reading from port 0 when there was no device there.

Best Regards,
FTDI Community
Logged