-
Notifications
You must be signed in to change notification settings - Fork 6
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
Loopback FTDI implementation on the FX2 using USB descriptors from the linux-descriptors branch #21
base: linux-descriptors
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#!/bin/bash -e | ||
|
||
DEVS=$(lsusb|grep -E '(2a19|16c0|04b4|1d50|fb9a|1443)' |sed 's/:.*//;s/Bus //;s/Device //;s/ /\//') | ||
|
||
if [ -z "$1" ]; then | ||
echo "$0: usage: $0 <file>" | ||
exit 1; | ||
fi | ||
|
||
for dev in $DEVS;do | ||
echo "Downloading $1 to $dev" | ||
/sbin/fxload -D /dev/bus/usb/$dev -t fx2lp -I $1 | ||
done | ||
|
||
exit 0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
FX2LIBDIR=../../ | ||
BASENAME = ftdi_main | ||
SOURCES=ftdi_main.c ftdi_conf.c | ||
PID=0x1004 | ||
CODE_SIZE = --code-size 0x3000 | ||
XRAM_LOC = --xram-loc 0x3200 | ||
XRAM_SIZE = --xram-size 0x700 | ||
INT2JT =-Wl"-b INT2JT=0x3100" | ||
include $(FX2LIBDIR)lib/fx2.mk | ||
include $(FX2LIBDIR)lib/fx2-cdesc.mk | ||
fx2_download: | ||
../download.sh build/$(BASENAME).ihx |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
/* | ||
The descriptors below setup an FTDI device with a VID | ||
of 0x0403, and PID of 0x6010.In this particular case | ||
endpoint 1 is used to transfer data in and out of the device | ||
since it can be easily accessed by the CPU and is not used | ||
for other purposes(Typically used for transferring small amounts | ||
of data which is what we need) | ||
lsusb -v will show: | ||
vbDevice Descriptor: | ||
bLength 18 | ||
bDescriptorType 1 | ||
bcdUSB 2.00 | ||
bDeviceClass 255 Vendor Specific Class | ||
bDeviceSubClass 255 Vendor Specific Subclass | ||
bDeviceProtocol 255 Vendor Specific Protocol | ||
bMaxPacketSize0 64 | ||
idVendor 0x0403 Future Technology Devices International, Ltd | ||
idProduct 0x6010 FT2232C Dual USB-UART/FIFO IC | ||
bcdDevice 0.01 | ||
iManufacturer 1 | ||
iProduct 2 | ||
iSerial 0 | ||
bNumConfigurations 1 | ||
Configuration Descriptor: | ||
bLength 9 | ||
bDescriptorType 2 | ||
wTotalLength 32 | ||
bNumInterfaces 1 | ||
bConfigurationValue 1 | ||
iConfiguration 0 | ||
bmAttributes 0x80 | ||
(Bus Powered) | ||
MaxPower 100mA | ||
Interface Descriptor: | ||
bLength 9 | ||
bDescriptorType 4 | ||
bInterfaceNumber 0 | ||
bAlternateSetting 0 | ||
bNumEndpoints 2 | ||
bInterfaceClass 255 Vendor Specific Class | ||
bInterfaceSubClass 255 Vendor Specific Subclass | ||
bInterfaceProtocol 255 Vendor Specific Protocol | ||
iInterface 3 | ||
Endpoint Descriptor: | ||
bLength 7 | ||
bDescriptorType 5 | ||
bEndpointAddress 0x01 EP 1 OUT | ||
bmAttributes 2 | ||
Transfer Type Bulk | ||
Synch Type None | ||
Usage Type Data | ||
wMaxPacketSize 0x0200 1x 512 bytes | ||
bInterval 0 | ||
Endpoint Descriptor: | ||
bLength 7 | ||
bDescriptorType 5 | ||
bEndpointAddress 0x81 EP 1 IN | ||
bmAttributes 2 | ||
Transfer Type Bulk | ||
Synch Type None | ||
Usage Type Data | ||
wMaxPacketSize 0x0200 1x 512 bytes | ||
bInterval 0 | ||
*/ | ||
#include "descriptors.h" | ||
|
||
__code __at(0x3e00) struct usb_descriptors code_descriptors = | ||
{ | ||
.device = { | ||
.bLength = USB_DT_DEVICE_SIZE, | ||
.bDescriptorType = USB_DT_DEVICE, | ||
.bcdUSB = USB_BCD_V20, | ||
.bDeviceClass = USB_CLASS_VENDOR_SPEC, | ||
.bDeviceSubClass = USB_SUBCLASS_VENDOR_SPEC, | ||
.bDeviceProtocol = 0xff, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Include comment for bDeviceProtocol There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually is there a USB_PROTO_VENDOR_SPEC macro or similar? |
||
.bMaxPacketSize0 = 64, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Include comments for the fields below. |
||
.idVendor = 0x0403, | ||
.idProduct = 0x6010, | ||
.bcdDevice = 0x0001, | ||
.iManufacturer = USB_STRING_INDEX(0), | ||
.iProduct = USB_STRING_INDEX(1), | ||
.iSerialNumber = USB_STRING_INDEX_NONE, | ||
.bNumConfigurations = 1, | ||
}, | ||
.qualifier = { | ||
.bLength = USB_DT_DEVICE_QUALIFIER_SIZE, | ||
.bDescriptorType = USB_DT_DEVICE_QUALIFIER, | ||
.bcdUSB = USB_BCD_V20, | ||
.bDeviceClass = USB_CLASS_VENDOR_SPEC, | ||
.bDeviceSubClass = USB_SUBCLASS_VENDOR_SPEC, | ||
.bDeviceProtocol = 0xff, | ||
.bMaxPacketSize0 = 64, | ||
.bNumConfigurations = 1, | ||
.bRESERVED = 0, | ||
}, | ||
.highspeed = { | ||
.config = { | ||
.bLength = USB_DT_CONFIG_SIZE, | ||
.bDescriptorType = USB_DT_CONFIG, | ||
.wTotalLength = sizeof(descriptors.highspeed), | ||
.bNumInterfaces = 1, | ||
.bConfigurationValue = 1, | ||
.iConfiguration = 0, | ||
.bmAttributes = USB_CONFIG_ATT_ONE, | ||
.bMaxPower = 0x32, // FIXME: ??? | ||
}, | ||
.interface = { | ||
.bLength = USB_DT_INTERFACE_SIZE, | ||
.bDescriptorType = USB_DT_INTERFACE, | ||
.bInterfaceNumber = 0, | ||
.bAlternateSetting = 0, | ||
.bNumEndpoints = 2, | ||
.bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
.bInterfaceSubClass = USB_SUBCLASS_VENDOR_SPEC, | ||
.bInterfaceProtocol = USB_PROTOCOL_VENDOR_SPEC, | ||
.iInterface = USB_STRING_INDEX(2), | ||
}, | ||
.endpoints = { | ||
{ | ||
.bLength = USB_DT_ENDPOINT_SIZE, | ||
.bDescriptorType = USB_DT_ENDPOINT, | ||
.bEndpointAddress = USB_ENDPOINT_NUMBER(0x1) | USB_DIR_OUT, | ||
.bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
.wMaxPacketSize = 512, | ||
.bInterval = 0, | ||
}, | ||
{ | ||
.bLength = USB_DT_ENDPOINT_SIZE, | ||
.bDescriptorType = USB_DT_ENDPOINT, | ||
.bEndpointAddress = USB_ENDPOINT_NUMBER(0x1) | USB_DIR_IN, | ||
.bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
.wMaxPacketSize = 512, | ||
.bInterval = 0, | ||
}, | ||
}, | ||
}, | ||
.fullspeed = { | ||
.config = { | ||
.bLength = USB_DT_CONFIG_SIZE, | ||
.bDescriptorType = USB_DT_CONFIG, | ||
.wTotalLength = sizeof(descriptors.fullspeed), | ||
.bNumInterfaces = 1, | ||
.bConfigurationValue = 1, | ||
.iConfiguration = 0, | ||
.bmAttributes = USB_CONFIG_ATT_ONE, | ||
.bMaxPower = 0x32, // FIXME: ??? | ||
}, | ||
.interface = { | ||
.bLength = USB_DT_INTERFACE_SIZE, | ||
.bDescriptorType = USB_DT_INTERFACE, | ||
.bInterfaceNumber = 0, | ||
.bAlternateSetting = 0, | ||
.bNumEndpoints = 2, | ||
.bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
.bInterfaceSubClass = USB_SUBCLASS_VENDOR_SPEC, | ||
.bInterfaceProtocol = 0xff, | ||
.iInterface = 3, | ||
}, | ||
.endpoints = { | ||
{ | ||
.bLength = USB_DT_ENDPOINT_SIZE, | ||
.bDescriptorType = USB_DT_ENDPOINT, | ||
.bEndpointAddress = USB_ENDPOINT_NUMBER(0x2) | USB_DIR_OUT, | ||
.bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
.wMaxPacketSize = 64, | ||
.bInterval = 0, | ||
}, | ||
{ | ||
.bLength = USB_DT_ENDPOINT_SIZE, | ||
.bDescriptorType = USB_DT_ENDPOINT, | ||
.bEndpointAddress = USB_ENDPOINT_NUMBER(0x6) | USB_DIR_IN, | ||
.bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
.wMaxPacketSize = 64, | ||
.bInterval = 0, | ||
}, | ||
}, | ||
}, | ||
#include "build/descriptors_stringtable.inc" | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#include <stddef.h> | ||
|
||
#include "build/descriptors_stringtable.h" | ||
|
||
#include <linux/ch9.h> | ||
#include <linux/ch9-extra.h> | ||
|
||
#ifndef DESCRIPTORS_H_ | ||
#define DESCRIPTORS_H_ | ||
|
||
struct usb_section { | ||
struct usb_config_descriptor config; | ||
struct usb_interface_descriptor interface; | ||
struct usb_endpoint_descriptor endpoints[2]; | ||
}; | ||
|
||
struct usb_descriptors { | ||
struct usb_device_descriptor device; | ||
struct usb_qualifier_descriptor qualifier; | ||
struct usb_section highspeed; | ||
struct usb_section fullspeed; | ||
struct usb_descriptors_stringtable stringtable; | ||
}; | ||
|
||
__xdata __at(DSCR_AREA) struct usb_descriptors descriptors; | ||
|
||
__code __at(DSCR_AREA+offsetof(struct usb_descriptors, device)) WORD dev_dscr; | ||
__code __at(DSCR_AREA+offsetof(struct usb_descriptors, qualifier)) WORD dev_qual_dscr; | ||
__code __at(DSCR_AREA+offsetof(struct usb_descriptors, highspeed)) WORD highspd_dscr; | ||
__code __at(DSCR_AREA+offsetof(struct usb_descriptors, fullspeed)) WORD fullspd_dscr; | ||
__code __at(DSCR_AREA+offsetof(struct usb_descriptors, stringtable)) WORD dev_strings; | ||
|
||
#endif // DESCRIPTORS_H_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Hi | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fill these with real appropriate values |
||
There | ||
iFrame |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
#include "ftdi_conf.h" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Put the include after the initial comment. |
||
/* -*- mode: C; c-basic-offset: 3; -*- | ||
* | ||
* convert_serial -- FX2 USB serial port converter | ||
* | ||
* by Brent Baccala <cosine@freesoft.org> July 2009 | ||
* adapted by Roarin | ||
* | ||
* Based on both usb-fx2-local-examples by Wolfgang Wieser (GPLv2) and | ||
* the Cypress FX2 examples. | ||
* | ||
* This is an FX2 program which re-enumerates to mimic a USB-attached | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you still emulating a FT8U100AX? |
||
* serial port (an FT8U100AX). Anything transmitted to it by the host | ||
* is echoed back after converting lowercase to uppercase. The | ||
* re-enumerated FX2 appears on a Debian Linux machine as something | ||
* like /dev/ttyUSB0, and can be tested with a serial port program | ||
* like 'minicom'. | ||
* | ||
* An actual FT8U100AX transmits and receives on endpoint 2. Since | ||
* the FX2's endpoint 2 can be configured to either send or receive | ||
* (but not do both), we use endpoint 1. This works with the Linux | ||
* driver, which reads the endpoint addresses from the USB | ||
* descriptors, but might not work with some other driver where the | ||
* endpoint addresses are hardwired in the driver code. | ||
* | ||
* Many features, like setting and querying things like the baudrate | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you planning on implementing these? |
||
* and line/modem status are unimplemented, and will return USB errors | ||
* when the host attempts to perform these operations. However, the | ||
* program works, and I decided to leave out the additional clutter in | ||
* favor of a simpler program that can be easily modified to suit | ||
* individual needs. | ||
* | ||
* The program ignores USB Suspend interrupts, and probably violates | ||
* the USB standard in this regard, as all USB devices are required to | ||
* support Suspend. The remote wakeup feature is parsed and correctly | ||
* handled in the protocol, but of course does nothing since the | ||
* device never suspends. | ||
*/ | ||
unsigned char bytes_waiting_for_xmit = 0; | ||
|
||
void configure_endpoints(void) | ||
{ | ||
|
||
REVCTL=0x03; // See TRM... | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See TRM is not a useful comment. Explain why. |
||
SYNCDELAY; | ||
// Endpoint configuration - everything disabled except | ||
// bidirectional transfers on EP1. | ||
EP1OUTCFG=0xa0; | ||
EP1INCFG=0xa0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use macros to work out this value. |
||
EP2CFG=0; | ||
EP4CFG=0; | ||
EP6CFG=0; | ||
EP8CFG=0; | ||
SYNCDELAY; | ||
EP1OUTBC=0xff; // Arm endpoint 1 for OUT (host->device) transfers | ||
} | ||
|
||
// We want to buffer any outgoing data for a short time (40 ms) to see | ||
// if any other data becomes available and it can all be sent | ||
// together. At 12 MHz we consume 83.3 ns/cycle and divide this rate | ||
// by 12 so that our counters increment almost exactly once every us. | ||
// The counter is sixteen bits, so we can specify latencies up to | ||
// about 65 ms. | ||
void process_send_data(void) | ||
{ | ||
// Lead in two bytes in the returned data (modem status and | ||
// line status). | ||
EP1INBUF[0] = FTDI_RS0_CTS | FTDI_RS0_DSR | 1; | ||
EP1INBUF[1] = FTDI_RS_DR; | ||
// Send the packet. | ||
SYNCDELAY; | ||
EP1INBC = bytes_waiting_for_xmit + 2; | ||
bytes_waiting_for_xmit = 0; | ||
} | ||
|
||
void putchar_usb(char c) | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this indented differently? |
||
__xdata unsigned char *dest=EP1INBUF + bytes_waiting_for_xmit + 2; | ||
// Wait (if needed) for EP1INBUF ready to accept data | ||
while (EP1INCS & 0x02); | ||
*dest = c; | ||
if (++bytes_waiting_for_xmit >= 1) process_send_data(); | ||
} | ||
|
||
void process_recv_data(void) | ||
{ | ||
__xdata const unsigned char *src=EP1OUTBUF; | ||
unsigned int len = EP1OUTBC; | ||
unsigned int i; | ||
// Skip the first byte in the received data (it's a port | ||
// identifier and length). | ||
src++; len--; | ||
for(i=0; i<len; i++,src++) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this wrapped differently from everything else? |
||
{ | ||
if(*src>='a' && *src<='z') | ||
{ putchar_usb(*src-'a'+'A'); } | ||
else | ||
{ putchar_usb(*src); } | ||
} | ||
EP1OUTBC=0xff; // re-arm endpoint 1 for OUT (host->device) transfers | ||
SYNCDELAY; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/** \file ftdi_conf.h | ||
* Definitions for FTDI devices | ||
**/ | ||
#ifndef FTDI_CONF_H | ||
#define FTDI_CONFH | ||
#include "fx2types.h" | ||
#include <delay.h> | ||
#include <fx2regs.h> | ||
// These defines came from the Linux source code: | ||
// drivers/usb/serial/ftdi_sio.h | ||
// That file also does a reasonable job of documenting the protocol, | ||
// particularly the vendor requests I don't implement that do things | ||
// like setting the baud rate. | ||
#define FTDI_RS0_CTS (1 << 4) | ||
#define FTDI_RS0_DSR (1 << 5) | ||
#define FTDI_RS0_RI (1 << 6) | ||
#define FTDI_RS0_RLSD (1 << 7) | ||
#define FTDI_RS_DR 1 | ||
#define FTDI_RS_OE (1<<1) | ||
#define FTDI_RS_PE (1<<2) | ||
#define FTDI_RS_FE (1<<3) | ||
#define FTDI_RS_BI (1<<4) | ||
#define FTDI_RS_THRE (1<<5) | ||
#define FTDI_RS_TEMT (1<<6) | ||
#define FTDI_RS_FIFO (1<<7) | ||
//Used for delay definition | ||
#define SYNCDELAY SYNCDELAY4 | ||
/** | ||
* \brief Configures endpoint 1 | ||
**/ | ||
void configure_endpoints(void); | ||
/** | ||
* \brief Send data present in EP1INBUF out | ||
**/ | ||
void process_send_data(void); | ||
/** | ||
* \brief Inserts data into endpoint buffer | ||
**/ | ||
void putchar_usb(char c); | ||
/** | ||
* \brief Receives data from endpoint 1, and calls putchar_usb | ||
**/ | ||
void process_recv_data(void); | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mixing tab and spaces here which is causing the weird indentation issues.