Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for USB Host / CDC Devices based on FTDI chipsets (FT232) #7

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.a
*.o
.DS_Store
build/
1 change: 1 addition & 0 deletions _sdk/src/sdk_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ void UartStdioHandler(void)
while (UART_RecvReady(UART_STDIO_PORT)) // received data ready
{
ch = UART_RecvChar(UART_STDIO_PORT); // receive character from UART
UartPrint("%c", ch); // echo character
if (RingWriteReady(&UartStdioRxBuf, 1)) // if space in receive buffer
RingWrite8(&UartStdioRxBuf, ch); // write character
// otherwise lost received data if receive buffer is full
Expand Down
2 changes: 2 additions & 0 deletions _sdk/usb_inc/sdk_usb_host_cdc.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,11 @@ void UsbHostCdcTerm();
// open class interface (returns size of used interface, 0=not supported)
// - At this point, no communications are allowed yet.
u16 UsbHostCdcOpen(u8 dev_addr, const sUsbDescItf* itf, u16 max_len);
u16 UsbHostCdcOpenFTDI(u8 dev_addr, const sUsbDescItf* itf, u16 max_len);

// set config interface
Bool UsbHostCdcCfg(u8 dev_addr, u8 itf_num);
Bool UsbHostCdcCfgFTDI(u8 dev_addr, u8 itf_num);

// transfer complete callback
Bool UsbHostCdcComp(u8 dev_addr, u8 dev_epinx, u8 xres, u16 len);
Expand Down
11 changes: 9 additions & 2 deletions _sdk/usb_src/sdk_usb_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include "../inc/sdk_irq.h"
#include "../inc/sdk_timer.h"
#include "../inc/sdk_uart.h"
#include "../usb_inc/sdk_usb_host.h"
#include "../usb_inc/sdk_usb_host_cdc.h" // USB Communication Device Class (host)
#include "../usb_inc/sdk_usb_host_hid.h" // USB Human Interface Device Class (host)
Expand Down Expand Up @@ -59,8 +60,8 @@ const sUsbHostDrv UsbHostDrv[] = {
{
UsbHostCdcInit, // initialize class driver
UsbHostCdcTerm, // terminate class driver
UsbHostCdcOpen, // open device class interface
UsbHostCdcCfg, // configure interface
UsbHostCdcOpenFTDI, // open device class interface
UsbHostCdcCfgFTDI, // configure interface
UsbHostCdcComp, // transfer complete callback
UsbHostCdcClose, // close device
UsbHostCdcSof, // sending SOF (start of frame; NULL=not used)
Expand Down Expand Up @@ -401,6 +402,8 @@ Bool UsbHostParseCfg(u8 dev_addr, const u8* p_desc)
// some CDC devices does not use interface association, need to set 2 interfaces manually
if ((assoc == 1) && (desc_itf->itf_class == USB_CLASS_CDC) && (desc_itf->itf_subclass == 2)) assoc = 2;

assoc = 2; // FIXME: force this for now for CDC/FTDI

// search support of this interface in class device drivers
u16 rem_len = desc_end - p_desc; // remaining length
u8 drv_id;
Expand Down Expand Up @@ -506,6 +509,8 @@ Bool UsbHostGetDesc(u8 dev_addr, u8 desc_type, u8 inx, u16 lang, void* buf, u16
// is marked as mounted.
void UsbHostCfgComp(u8 dev_addr, u8 itf_num)
{
UartPrint("UsbHostCfgComp(%u,%u)\n", dev_addr, itf_num);

// continue to next interface
itf_num++;

Expand Down Expand Up @@ -556,6 +561,8 @@ void UsbHostCfgComp(u8 dev_addr, u8 itf_num)
// xres ... transfer result USB_XRES_*
void UsbHostEnum(u8 dev_addr, u8 xres)
{
UartPrint("UsbHostEnum(%u)\n", UsbHostEnumState);

// idle
if (UsbHostEnumState == USB_HOST_ENUM_IDLE) return;

Expand Down
94 changes: 94 additions & 0 deletions _sdk/usb_src/sdk_usb_host_cdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#if USE_USB_HOST_CDC // use USB CDC Communication Device Class, value = number of interfaces (host)

#include "../inc/sdk_timer.h"
#include "../inc/sdk_uart.h"
#include "../usb_inc/sdk_usb_host.h"
#include "../usb_inc/sdk_usb_host_cdc.h"

Expand Down Expand Up @@ -211,6 +212,8 @@ void UsbHostCdcAllRecv()
// initialize class driver
void UsbHostCdcInit()
{
UartPrint("UsbHostCdcInit\n");

memset(UsbHostCdcInter, 0, sizeof(UsbHostCdcInter));

u8 cdc_inx;
Expand All @@ -231,6 +234,34 @@ void UsbHostCdcTerm()

}

// FTDI device open
u16 UsbHostCdcOpenFTDI(u8 dev_addr, const sUsbDescItf* itf, u16 max_len)
{
UartPrint("UsbHostCdcOpenFTDI\n"); // FTDI includes 1 vendor interface and 2 bulk endpoints

// check descriptor size
if (USB_DESC_LEN(itf) > max_len) return 0;

// allocate new interface
u8 cdc_inx = UsbHostCdcNewItf(dev_addr, itf);
if (cdc_inx == USB_DRVID_INVALID) return 0;

// pointer to CDC interface
sUsbHostCdcInter* cdc = &UsbHostCdcInter[cdc_inx];

// skip interface descriptor
u16 drv_len = USB_DESC_LEN(itf);
const u8* p_desc = USB_DESC_NEXT(itf);

// open endpoint pair
if (!UsbHostOpenEpPair(dev_addr, p_desc, 2, &cdc->ep_out, &cdc->ep_in, NULL, NULL)) return 0;

// skip endpoint descriptors
drv_len += 2*sizeof(sUsbDescEp);

return drv_len;
}

// open class interface (returns size of used interface, 0=not supported)
// - At this point, no communications are allowed yet.
u16 UsbHostCdcOpen(u8 dev_addr, const sUsbDescItf* itf, u16 max_len)
Expand Down Expand Up @@ -321,6 +352,69 @@ void UsbHostCdcCfgComp(u8 dev_addr, u8 xres)
UsbHostCfgComp(dev_addr, itf_num+1);
}

void UsbHostCdcCfgFTDILine(u8 dev_addr, u8 xres)
{
UartPrint("UsbHostCdcCfgFTDILine\n");

// pointer to setup packet
sUsbSetupPkt* setup = &UsbSetupRequest;

// FTDI line setting
setup->type = 0x40 ; // out | vendor | device
setup->request = 0x01 ; // line state
setup->value = 0x0303; // enable DTR/RTS
setup->index = 0x0000; // no index
setup->length = 0x0000; // no data

// send data
UsbHostCtrlXfer(dev_addr, NULL, UsbHostCdcCfgComp);
}

void UsbHostCdcCfgFTDIBaud(u8 dev_addr, u8 xres)
{
UartPrint("UsbHostCdcCfgFTDIBaud\n");

// pointer to setup packet
sUsbSetupPkt* setup = &UsbSetupRequest;

// FTDI baud rate
setup->type = 0x40 ; // out | vendor | device
setup->request = 0x03 ; // set baud rate
setup->value = 0x4138; // 9600 baud (3MHz/312.5)
setup->index = 0x0000; // no index
setup->length = 0x0000; // no data

// send data
UsbHostCtrlXfer(dev_addr, NULL, UsbHostCdcCfgFTDILine);
}

Bool UsbHostCdcCfgFTDI (u8 dev_addr, u8 itf_num)
{
UartPrint("UsbHostCdcCfgFTDI\n");

// find interface by interface number (returns interface index, or USB_DRVID_INVALID if not found)
u8 cdc_inx = UsbHostCdcFindItf(dev_addr, itf_num);
if (cdc_inx == USB_DRVID_INVALID) return False;

// pointer to CDC interface
sUsbHostCdcInter* cdc = &UsbHostCdcInter[cdc_inx];

// pointer to setup packet
sUsbSetupPkt* setup = &UsbSetupRequest;

// FTDI controller reset
setup->type = 0x40 ; // out | vendor | device
setup->request = 0x00 ; // reset
setup->value = 0x0000; // purges RX/TX, clears DTR/RTS, data as 8N1, leave baud
setup->index = 0x0000; // no index
setup->length = 0x0000; // no data

// send data
UsbHostCdcCfg_Itf = itf_num; // temporary save interface
UsbHostCtrlXfer(dev_addr, NULL, UsbHostCdcCfgFTDIBaud);
return True;
}

// set config interface
Bool UsbHostCdcCfg(u8 dev_addr, u8 itf_num)
{
Expand Down
8 changes: 4 additions & 4 deletions _setup.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ case "$1" in
export DEVCLASS="pico"
export DEVDIR="!Pico"
;;
*)
export DEVICE="picopad10"
export DEVCLASS="picopad"
export DEVDIR="!PicoPad10"
*)
export DEVICE="pico"
export DEVCLASS="pico"
export DEVDIR="!Pico"
;;
esac

Expand Down