Remove unused code
This commit is contained in:
@@ -1,9 +0,0 @@
|
||||
#ifndef _GPIO_H
|
||||
#define _GPIO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define USB_GPIO (uint8_t*)0x7ff1
|
||||
extern uint8_t* usb_gpio;
|
||||
|
||||
#endif
|
||||
9
sw/io.h
9
sw/io.h
@@ -1,9 +0,0 @@
|
||||
#ifndef _IO_H
|
||||
#define _IO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define USB_GPIO 0x7ff1
|
||||
extern uint8_t* usb_gpio;
|
||||
|
||||
#endif
|
||||
9
sw/spi.h
9
sw/spi.h
@@ -1,9 +0,0 @@
|
||||
#ifndef _SPI_H
|
||||
#define _SPI_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t spi_byte(uint8_t);
|
||||
void spi_deselect(void);
|
||||
|
||||
#endif
|
||||
62
sw/spi.s
62
sw/spi.s
@@ -1,62 +0,0 @@
|
||||
.include "io.inc65"
|
||||
|
||||
.export _spi_byte
|
||||
.export _spi_deselect
|
||||
|
||||
.importzp sp, sreg, regsave, regbank
|
||||
.importzp tmp1, tmp2, tmp3, tmp4, ptr1, ptr2, ptr3, ptr4
|
||||
|
||||
.code
|
||||
|
||||
SPI_SCLK = $01
|
||||
SPI_SSn = $02
|
||||
SPI_MOSI = $04
|
||||
SPI_MISO = $08
|
||||
|
||||
|
||||
; Read and write a single byte from the SPI device
|
||||
; @in A The byte to write
|
||||
; @out A The read byte
|
||||
|
||||
_spi_byte:
|
||||
phx ; Save regs
|
||||
phy
|
||||
ldy #$00
|
||||
sta tmp1 ; Save value into tmp1
|
||||
lda #$80
|
||||
tax
|
||||
@loop: bit tmp1 ; Check if high bit set
|
||||
beq @1
|
||||
lda #SPI_MOSI ; Bit not set.
|
||||
bra @1
|
||||
@1: lda #$00 ; Bit set
|
||||
sta BB_SPI_BASE ; Write data
|
||||
adc #SPI_SCLK
|
||||
sta BB_SPI_BASE ; Write clock
|
||||
stz tmp2
|
||||
lda BB_SPI_BASE ; Check MISO value
|
||||
and #SPI_MISO
|
||||
beq @2
|
||||
inc tmp2
|
||||
@2: clc ; Shift previous value left
|
||||
tya ; Add current value
|
||||
asl
|
||||
adc tmp2
|
||||
tay ; Move read value back to y
|
||||
txa
|
||||
lsr ; Select next bit
|
||||
tax
|
||||
bne @loop ; Stop when mask is 0
|
||||
tya ; Get read value from y
|
||||
ply
|
||||
plx
|
||||
rts ; Return
|
||||
|
||||
; Deselect the spi device.
|
||||
; spi device is automatically selected during read/write.
|
||||
_spi_deselect:
|
||||
pha
|
||||
lda #SPI_SSn ; Raise Slave Select
|
||||
sta BB_SPI_BASE
|
||||
pla
|
||||
rts
|
||||
@@ -1,9 +0,0 @@
|
||||
/* Generic macros */
|
||||
|
||||
/* Word <> two chars. Works both ways */
|
||||
#define LOBYTE(x) ((char*)(&(x)))[0]
|
||||
#define HIBYTE(x) ((char*)(&(x)))[1]
|
||||
|
||||
/* Bit set/clear */
|
||||
#define bitset(var, bitno) ((var) |= 1 << (bitno))
|
||||
#define bitclr(var, bitno) ((var) &= ~(1 << (bitno)))
|
||||
@@ -1,115 +0,0 @@
|
||||
//Modified version of Generic Types as included by Microchip C18
|
||||
|
||||
#ifndef __GENERIC_TYPE_DEFS_H_
|
||||
#define __GENERIC_TYPE_DEFS_H_
|
||||
|
||||
typedef enum _BOOL {
|
||||
FALSE = 0, TRUE
|
||||
} BOOL; // Undefined size
|
||||
|
||||
#define ON TRUE
|
||||
#define OFF FALSE
|
||||
|
||||
typedef unsigned char BYTE; // 8-bit unsigned
|
||||
typedef unsigned short int WORD; // 16-bit unsigned
|
||||
typedef unsigned long DWORD; // 32-bit unsigned
|
||||
typedef signed char CHAR; // 8-bit signed
|
||||
typedef signed short int SHORT; // 16-bit signed
|
||||
typedef signed long LONG; // 32-bit signed
|
||||
|
||||
typedef union _BYTE_VAL {
|
||||
BYTE Val;
|
||||
struct {
|
||||
unsigned int b0 :1;
|
||||
unsigned int b1 :1;
|
||||
unsigned int b2 :1;
|
||||
unsigned int b3 :1;
|
||||
unsigned int b4 :1;
|
||||
unsigned int b5 :1;
|
||||
unsigned int b6 :1;
|
||||
unsigned int b7 :1;
|
||||
} bits;
|
||||
} BYTE_VAL;
|
||||
|
||||
typedef union _WORD_VAL {
|
||||
WORD Val;
|
||||
BYTE v[2];
|
||||
struct {
|
||||
BYTE LB;
|
||||
BYTE HB;
|
||||
} byte;
|
||||
struct {
|
||||
unsigned int b0 :1;
|
||||
unsigned int b1 :1;
|
||||
unsigned int b2 :1;
|
||||
unsigned int b3 :1;
|
||||
unsigned int b4 :1;
|
||||
unsigned int b5 :1;
|
||||
unsigned int b6 :1;
|
||||
unsigned int b7 :1;
|
||||
unsigned int b8 :1;
|
||||
unsigned int b9 :1;
|
||||
unsigned int b10 :1;
|
||||
unsigned int b11 :1;
|
||||
unsigned int b12 :1;
|
||||
unsigned int b13 :1;
|
||||
unsigned int b14 :1;
|
||||
unsigned int b15 :1;
|
||||
} bits;
|
||||
} WORD_VAL;
|
||||
|
||||
typedef union _DWORD_VAL {
|
||||
DWORD Val;
|
||||
WORD w[2];
|
||||
BYTE v[4];
|
||||
struct {
|
||||
WORD LW;
|
||||
WORD HW;
|
||||
} word;
|
||||
struct {
|
||||
BYTE LB;
|
||||
BYTE HB;
|
||||
BYTE UB;
|
||||
BYTE MB;
|
||||
} byte;
|
||||
struct {
|
||||
unsigned int b0 :1;
|
||||
unsigned int b1 :1;
|
||||
unsigned int b2 :1;
|
||||
unsigned int b3 :1;
|
||||
unsigned int b4 :1;
|
||||
unsigned int b5 :1;
|
||||
unsigned int b6 :1;
|
||||
unsigned int b7 :1;
|
||||
unsigned int b8 :1;
|
||||
unsigned int b9 :1;
|
||||
unsigned int b10 :1;
|
||||
unsigned int b11 :1;
|
||||
unsigned int b12 :1;
|
||||
unsigned int b13 :1;
|
||||
unsigned int b14 :1;
|
||||
unsigned int b15 :1;
|
||||
unsigned int b16 :1;
|
||||
unsigned int b17 :1;
|
||||
unsigned int b18 :1;
|
||||
unsigned int b19 :1;
|
||||
unsigned int b20 :1;
|
||||
unsigned int b21 :1;
|
||||
unsigned int b22 :1;
|
||||
unsigned int b23 :1;
|
||||
unsigned int b24 :1;
|
||||
unsigned int b25 :1;
|
||||
unsigned int b26 :1;
|
||||
unsigned int b27 :1;
|
||||
unsigned int b28 :1;
|
||||
unsigned int b29 :1;
|
||||
unsigned int b30 :1;
|
||||
unsigned int b31 :1;
|
||||
} bits;
|
||||
} DWORD_VAL;
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#endif //__GENERIC_TYPE_DEFS_H_
|
||||
242
sw/usb/HID.c
242
sw/usb/HID.c
@@ -1,242 +0,0 @@
|
||||
/* HID class support functions */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "project_config.h"
|
||||
|
||||
BYTE bigbuf[256]; //256 bytes
|
||||
extern DEV_RECORD devtable[];
|
||||
|
||||
HID_DEVICE hid_device = { { 0 } };
|
||||
EP_RECORD hid_ep[2] = { { 0 } }; //HID class endpoints, 1 control, 1 interrupt-IN
|
||||
//the third endpoint is not implemented
|
||||
|
||||
/* HID Mouse probe. Called from USB state machine. */
|
||||
/* assumes configuration length is less than 256 bytes */
|
||||
/* looks for Class:03, Subclass: 01, Protocol: 02 in interface descriptor */
|
||||
/* sets mouse in boot protocol */
|
||||
/* assumes single configuration and interface configuration 0 */
|
||||
BOOL HIDMProbe(BYTE addr, DWORD flags) {
|
||||
BYTE tmpbyte;
|
||||
BYTE rcode;
|
||||
BYTE confvalue;
|
||||
WORD total_length;
|
||||
USB_DESCR* data_ptr = (USB_DESCR *) &bigbuf;
|
||||
BYTE* byte_ptr = bigbuf;
|
||||
|
||||
(void) flags;
|
||||
|
||||
rcode = XferGetConfDescr(addr, 0, CONF_DESCR_LEN, 0, bigbuf); //get configuration descriptor
|
||||
if (rcode) { //error handling
|
||||
//printf("unable to get configuration descriptor");
|
||||
return (FALSE);
|
||||
}
|
||||
if (data_ptr->descr.config.wTotalLength > 256) {
|
||||
total_length = 256;
|
||||
} else {
|
||||
total_length = data_ptr->descr.config.wTotalLength;
|
||||
}
|
||||
rcode = XferGetConfDescr(addr, 0, total_length, 0, bigbuf); //get the whole configuration
|
||||
if (rcode) { //error handling
|
||||
//printf("unable to get configuration");
|
||||
return (FALSE);
|
||||
}
|
||||
confvalue = data_ptr->descr.config.bConfigurationValue;
|
||||
//printf("checking configuration value (length: %d): ",
|
||||
// data_ptr->descr.config.wTotalLength);
|
||||
//for (int i = 0; i < data_ptr->descr.config.wTotalLength; i++) {
|
||||
//printf("%x ", (unsigned char) (bigbuf[i] & 0xff));
|
||||
//}
|
||||
while (byte_ptr < bigbuf + total_length) {
|
||||
if (data_ptr->descr.config.bDescriptorType != USB_DESCRIPTOR_INTERFACE) {
|
||||
byte_ptr = byte_ptr + data_ptr->descr.config.bLength;
|
||||
data_ptr = (USB_DESCR*) byte_ptr;
|
||||
} // if( data_ptr->descr.config.bDescriptorType != USB_DESCRIPTOR_INTERFACE
|
||||
else {
|
||||
//printf("starting interface parsing at byte location %d\n",
|
||||
// data_ptr->descr.config.bLength);
|
||||
BYTE class = data_ptr->descr.interface.bInterfaceClass;
|
||||
BYTE subclass = data_ptr->descr.interface.bInterfaceSubClass;
|
||||
BYTE protocol = data_ptr->descr.interface.bInterfaceProtocol;
|
||||
//printf("class %x, subclass %x, protocol %x,\n", class, subclass,
|
||||
// protocol);
|
||||
//interface descriptor
|
||||
if (class == HID_INTF && subclass == BOOT_INTF_SUBCLASS
|
||||
&& protocol == HID_PROTOCOL_MOUSE) {
|
||||
//detected a mouse
|
||||
devtable[addr].devclass = HID_M; //device class
|
||||
tmpbyte = devtable[addr].epinfo->MaxPktSize;
|
||||
HID_init(); //initialize data structures
|
||||
devtable[addr].epinfo = hid_ep; //switch endpoint information structure
|
||||
devtable[addr].epinfo[0].MaxPktSize = tmpbyte;
|
||||
hid_device.interface =
|
||||
data_ptr->descr.interface.bInterfaceNumber;
|
||||
hid_device.addr = addr;
|
||||
byte_ptr = byte_ptr + data_ptr->descr.config.bLength;
|
||||
data_ptr = (USB_DESCR*) byte_ptr;
|
||||
while (byte_ptr < bigbuf + total_length) {
|
||||
if (data_ptr->descr.config.bDescriptorType
|
||||
!= USB_DESCRIPTOR_ENDPOINT) { //skip to endpoint descriptor
|
||||
byte_ptr = byte_ptr + data_ptr->descr.config.bLength;
|
||||
data_ptr = (USB_DESCR*) byte_ptr;
|
||||
} else {
|
||||
/* fill endpoint information structure */
|
||||
devtable[addr].epinfo[1].epAddr =
|
||||
data_ptr->descr.endpoint.bEndpointAddress;
|
||||
devtable[addr].epinfo[1].Attr =
|
||||
data_ptr->descr.endpoint.bmAttributes;
|
||||
devtable[addr].epinfo[1].MaxPktSize =
|
||||
data_ptr->descr.endpoint.wMaxPacketSize;
|
||||
devtable[addr].epinfo[1].Interval =
|
||||
data_ptr->descr.endpoint.bInterval;
|
||||
// devtable[ addr ].epinfo[ 1 ].rcvToggle = bmRCVTOG0;
|
||||
/* configure device */
|
||||
rcode = XferSetConf(addr, 0, confvalue); //set configuration
|
||||
if (rcode) { //error handling
|
||||
return (FALSE);
|
||||
}
|
||||
rcode = XferSetProto(addr, 0, hid_device.interface,
|
||||
BOOT_PROTOCOL);
|
||||
if (rcode) { //error handling
|
||||
return (FALSE);
|
||||
} else {
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
} //while( byte_ptr....
|
||||
} //if (Class matches
|
||||
else { //if class don't match; die on first interface. Not really correct
|
||||
return (FALSE);
|
||||
}
|
||||
} //else if( data_ptr->
|
||||
} // while( byte_ptr < &buf + total_length
|
||||
return (FALSE);
|
||||
}
|
||||
/* HID Keyboard probe. Called from USB state machine. */
|
||||
/* assumes configuration length is less than 256 bytes */
|
||||
/* looks for Class:03, Subclass: 01, Protocol: 01 in interface descriptor */
|
||||
/* sets keyboard in boot protocol */
|
||||
/* assumes single configuration, single endpoint, and interface configuration 0 */
|
||||
BOOL HIDKProbe(BYTE addr, DWORD flags) {
|
||||
BYTE tmpbyte;
|
||||
BYTE rcode;
|
||||
BYTE confvalue;
|
||||
WORD total_length;
|
||||
USB_DESCR* data_ptr = (USB_DESCR *) &bigbuf;
|
||||
BYTE* byte_ptr = bigbuf;
|
||||
|
||||
(void) flags;
|
||||
|
||||
rcode = XferGetConfDescr(addr, 0, CONF_DESCR_LEN, 0, bigbuf); //get configuration descriptor
|
||||
if (rcode) { //error handling
|
||||
return (FALSE);
|
||||
}
|
||||
if (data_ptr->descr.config.wTotalLength > 256) {
|
||||
total_length = 256;
|
||||
} else {
|
||||
total_length = data_ptr->descr.config.wTotalLength;
|
||||
}
|
||||
rcode = XferGetConfDescr(addr, 0, total_length, 0, bigbuf); //get the whole configuration
|
||||
if (rcode) { //error handling
|
||||
return (FALSE);
|
||||
}
|
||||
confvalue = data_ptr->descr.config.bConfigurationValue; //save configuration value to use later
|
||||
while (byte_ptr < bigbuf + total_length) { //parse configuration
|
||||
if (data_ptr->descr.config.bDescriptorType != USB_DESCRIPTOR_INTERFACE) { //skip to the next descriptor
|
||||
byte_ptr = byte_ptr + data_ptr->descr.config.bLength;
|
||||
data_ptr = (USB_DESCR*) byte_ptr;
|
||||
} // if( data_ptr->descr.config.bDescriptorType != USB_DESCRIPTOR_INTERFACE
|
||||
else {
|
||||
//printf("starting interface parsing at byte location %d\n",
|
||||
// data_ptr->descr.config.bLength);
|
||||
BYTE class = data_ptr->descr.interface.bInterfaceClass;
|
||||
BYTE subclass = data_ptr->descr.interface.bInterfaceSubClass;
|
||||
BYTE protocol = data_ptr->descr.interface.bInterfaceProtocol;
|
||||
//printf("class %x, subclass %x, protocol %x,\n", class, subclass,
|
||||
// protocol);
|
||||
//interface descriptor
|
||||
if (class == HID_INTF && subclass == BOOT_INTF_SUBCLASS
|
||||
&& protocol == HID_PROTOCOL_KEYBOARD) {
|
||||
//detected a keyboard
|
||||
devtable[addr].devclass = HID_K; //fill device class
|
||||
tmpbyte = devtable[addr].epinfo->MaxPktSize; //save max.packet size
|
||||
HID_init(); //initialize data structures
|
||||
devtable[addr].epinfo = hid_ep; //switch endpoint information structure
|
||||
devtable[addr].epinfo[0].MaxPktSize = tmpbyte; //fill in max.packet size
|
||||
hid_device.interface =
|
||||
data_ptr->descr.interface.bInterfaceNumber; //fill in interface number to be used in HID requests
|
||||
hid_device.addr = addr; //fill in address
|
||||
byte_ptr = byte_ptr + data_ptr->descr.config.bLength; //skip to the next descriptor
|
||||
data_ptr = (USB_DESCR*) byte_ptr;
|
||||
while (byte_ptr < bigbuf + total_length) {
|
||||
if (data_ptr->descr.config.bDescriptorType
|
||||
!= USB_DESCRIPTOR_ENDPOINT) { //skip to endpoint descriptor
|
||||
byte_ptr = byte_ptr + data_ptr->descr.config.bLength;
|
||||
data_ptr = (USB_DESCR*) byte_ptr;
|
||||
} else {
|
||||
/* fill endpoint information structure */
|
||||
devtable[addr].epinfo[1].epAddr =
|
||||
data_ptr->descr.endpoint.bEndpointAddress;
|
||||
devtable[addr].epinfo[1].Attr =
|
||||
data_ptr->descr.endpoint.bmAttributes;
|
||||
devtable[addr].epinfo[1].MaxPktSize =
|
||||
data_ptr->descr.endpoint.wMaxPacketSize;
|
||||
devtable[addr].epinfo[1].Interval =
|
||||
data_ptr->descr.endpoint.bInterval;
|
||||
/* configure device */
|
||||
rcode = XferSetConf(addr, 0, confvalue); //set configuration
|
||||
if (rcode) { //error handling
|
||||
return (FALSE);
|
||||
}
|
||||
rcode = XferSetProto(addr, 0, hid_device.interface,
|
||||
BOOT_PROTOCOL);
|
||||
if (rcode) { //error handling
|
||||
return (FALSE);
|
||||
} else {
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
} //while( byte_ptr....
|
||||
} //if (Class matches
|
||||
else { //if class don't match; stop processing after first interface. Not really correct
|
||||
return (FALSE);
|
||||
}
|
||||
} //else if( data_ptr->
|
||||
} // while( byte_ptr < &buf + total_length
|
||||
return (FALSE);
|
||||
}
|
||||
/* HID data structures initialization */
|
||||
void HID_init(void) {
|
||||
hid_ep[1].sndToggle = bmSNDTOG0;
|
||||
hid_ep[1].rcvToggle = bmRCVTOG0;
|
||||
}
|
||||
/* poll boot mouse */
|
||||
BYTE mousePoll(BOOT_MOUSE_REPORT* buf) {
|
||||
BYTE rcode;
|
||||
MAXreg_wr( rPERADDR, hid_device.addr); //set peripheral address
|
||||
rcode = XferInTransfer(hid_device.addr, 1, 8, (BYTE*) buf,
|
||||
devtable[hid_device.addr].epinfo[1].MaxPktSize);
|
||||
return (rcode);
|
||||
}
|
||||
/* poll boot keyboard */
|
||||
BYTE kbdPoll(BOOT_KBD_REPORT* buf) {
|
||||
BYTE rcode;
|
||||
MAXreg_wr( rPERADDR, hid_device.addr); //set peripheral address
|
||||
rcode = XferInTransfer(hid_device.addr, 1, 8, (BYTE*) buf,
|
||||
devtable[hid_device.addr].epinfo[1].MaxPktSize);
|
||||
return (rcode);
|
||||
}
|
||||
BOOL HIDMEventHandler(BYTE address, BYTE event, void *data, DWORD size) {
|
||||
(void) address;
|
||||
(void) event;
|
||||
(void) size;
|
||||
(void) data;
|
||||
return (FALSE);
|
||||
}
|
||||
BOOL HIDKEventHandler(BYTE address, BYTE event, void *data, DWORD size) {
|
||||
(void) address;
|
||||
(void) event;
|
||||
(void) size;
|
||||
(void) data;
|
||||
return (FALSE);
|
||||
}
|
||||
50
sw/usb/HID.h
50
sw/usb/HID.h
@@ -1,50 +0,0 @@
|
||||
/* HID support header */
|
||||
|
||||
#ifndef _HID_h_
|
||||
#define _HID_h
|
||||
|
||||
/* HID device structure */
|
||||
typedef struct {
|
||||
BYTE addr;
|
||||
BYTE interface;
|
||||
} HID_DEVICE;
|
||||
/* Boot mouse report 8 bytes */
|
||||
typedef struct {
|
||||
// struct {
|
||||
// unsigned one:1;
|
||||
// unsigned two:1;
|
||||
// unsigned three:1;
|
||||
// unsigned :5;
|
||||
// } button;
|
||||
BYTE button;
|
||||
BYTE Xdispl;
|
||||
BYTE Ydispl;
|
||||
BYTE bytes3to7[5]; //optional bytes
|
||||
} BOOT_MOUSE_REPORT;
|
||||
/* boot keyboard report 8 bytes */
|
||||
typedef struct {
|
||||
BYTE mod;
|
||||
// struct {
|
||||
// unsigned LCtrl:1;
|
||||
// unsigned LShift:1;
|
||||
// unsigned LAlt:1;
|
||||
// unsigned LWin:1;
|
||||
// /**/
|
||||
// unsigned RCtrl:1;
|
||||
// unsigned RShift:1;
|
||||
// unsigned RAlt:1;
|
||||
// unsigned RWin:1;
|
||||
// } mod;
|
||||
BYTE reserved;
|
||||
BYTE keycode[6];
|
||||
} BOOT_KBD_REPORT;
|
||||
|
||||
/* Function prototypes */
|
||||
BOOL HIDMProbe(BYTE address, DWORD flags);
|
||||
BOOL HIDKProbe(BYTE address, DWORD flags);
|
||||
void HID_init(void);
|
||||
BYTE mousePoll(BOOT_MOUSE_REPORT* buf);
|
||||
BYTE kbdPoll(BOOT_KBD_REPORT* buf);
|
||||
BOOL HIDMEventHandler(BYTE addr, BYTE event, void *data, DWORD size);
|
||||
BOOL HIDKEventHandler(BYTE addr, BYTE event, void *data, DWORD size);
|
||||
#endif // _HID_h_
|
||||
@@ -1,250 +0,0 @@
|
||||
//Fill in your low-level SPI functions here, as per your host platform
|
||||
|
||||
#define _MAX3421E_C_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "project_config.h"
|
||||
#include <spi.h>
|
||||
#include <gpio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
//variables and data structures
|
||||
//External variables
|
||||
extern BYTE usb_task_state;
|
||||
uint8_t* usb_gpio = USB_GPIO;
|
||||
|
||||
/* Functions */
|
||||
void SPI_init(BYTE sync_mode, BYTE bus_mode, BYTE smp_phase) {
|
||||
//Don't need to initialize SPI port, already ready to go with BSP
|
||||
(void) sync_mode;
|
||||
(void) bus_mode;
|
||||
(void) smp_phase;
|
||||
}
|
||||
|
||||
//writes single byte to MAX3421E via SPI, simultanously reads status register and returns it
|
||||
BYTE SPI_wr(BYTE data) {
|
||||
(void) data;
|
||||
//This function is never used by the code, so you do not need to fill it in
|
||||
return -1;
|
||||
}
|
||||
//writes register to MAX3421E via SPI
|
||||
void MAXreg_wr(BYTE reg, BYTE val) {
|
||||
//psuedocode:
|
||||
//select MAX3421E (may not be necessary if you are using SPI peripheral)
|
||||
//write reg + 2 via SPI
|
||||
//write val via SPI
|
||||
//read return code from SPI peripheral (see Intel documentation)
|
||||
//if return code < 0 print an error
|
||||
//deselect MAX3421E (may not be necessary if you are using SPI peripheral)
|
||||
BYTE regdir = reg + 2; //reg bitshift plus direction bit.
|
||||
|
||||
spi_byte(regdir);
|
||||
spi_byte(val);
|
||||
spi_deselect();
|
||||
}
|
||||
//multiple-byte write
|
||||
//returns a pointer to a memory position after last written
|
||||
BYTE* MAXbytes_wr(BYTE reg, BYTE nbytes, BYTE* data) {
|
||||
//psuedocode:
|
||||
//select MAX3421E (may not be necessary if you are using SPI peripheral)
|
||||
//write reg + 2 via SPI
|
||||
//write data[n] via SPI, where n goes from 0 to nbytes-1
|
||||
//read return code from SPI peripheral (see Intel documentation)
|
||||
//if return code < 0 print an error
|
||||
//deselect MAX3421E (may not be necessary if you are using SPI peripheral)
|
||||
//return (data + nbytes);
|
||||
int i;
|
||||
BYTE regdir = reg + 2;
|
||||
|
||||
spi_byte(regdir);
|
||||
|
||||
for (i = 0; i < nbytes; i++){
|
||||
spi_byte(data[i]);
|
||||
}
|
||||
|
||||
spi_deselect();
|
||||
|
||||
return data + nbytes;
|
||||
}
|
||||
|
||||
//reads register from MAX3421E via SPI
|
||||
BYTE MAXreg_rd(BYTE reg) {
|
||||
//psuedocode:
|
||||
//select MAX3421E (may not be necessary if you are using SPI peripheral)
|
||||
//write reg via SPI
|
||||
//read val via SPI
|
||||
//read return code from SPI peripheral (see Intel documentation)
|
||||
//if return code < 0 print an error
|
||||
//deselect MAX3421E (may not be necessary if you are using SPI peripheral)
|
||||
//return val
|
||||
BYTE regdir = reg;
|
||||
BYTE rxdata;
|
||||
|
||||
spi_byte(regdir);
|
||||
rxdata = spi_byte(0);
|
||||
spi_deselect();
|
||||
|
||||
return rxdata;
|
||||
}
|
||||
//multiple-byte write
|
||||
//returns a pointer to a memory position after last written
|
||||
BYTE* MAXbytes_rd(BYTE reg, BYTE nbytes, BYTE* data) {
|
||||
//psuedocode:
|
||||
//select MAX3421E (may not be necessary if you are using SPI peripheral)
|
||||
//write reg via SPI
|
||||
//read data[n] from SPI, where n goes from 0 to nbytes-1
|
||||
//read return code from SPI peripheral (see Intel documentation)
|
||||
//if return code < 0 print an error
|
||||
//deselect MAX3421E (may not be necessary if you are using SPI peripheral)
|
||||
//return (data + nbytes);
|
||||
int i;
|
||||
BYTE regdir = reg;
|
||||
|
||||
spi_byte(regdir);
|
||||
|
||||
for (i = 0; i < nbytes; i++){
|
||||
data[i] = spi_byte(0);
|
||||
}
|
||||
|
||||
spi_deselect();
|
||||
|
||||
return data + nbytes;
|
||||
}
|
||||
/* reset MAX3421E using chip reset bit. SPI configuration is not affected */
|
||||
void MAX3421E_reset(void) {
|
||||
//hardware reset, then software reset
|
||||
BYTE tmp;
|
||||
|
||||
*usb_gpio &= ~USB_GPIO_RST;
|
||||
//TODO
|
||||
//sleep(1);
|
||||
*usb_gpio |= USB_GPIO_RST;
|
||||
tmp = 0;
|
||||
MAXreg_wr( rUSBCTL, bmCHIPRES); //Chip reset. This stops the oscillator
|
||||
MAXreg_wr( rUSBCTL, 0x00); //Remove the reset
|
||||
while (!(MAXreg_rd( rUSBIRQ) & bmOSCOKIRQ)) { //wait until the PLL stabilizes
|
||||
tmp++; //timeout after 256 attempts
|
||||
if (tmp == 0) {
|
||||
//printf("reset timeout!");
|
||||
}
|
||||
}
|
||||
}
|
||||
/* turn USB power on/off */
|
||||
/* ON pin of VBUS switch (MAX4793 or similar) is connected to GPOUT7 */
|
||||
/* OVERLOAD pin of Vbus switch is connected to GPIN7 */
|
||||
/* OVERLOAD state low. NO OVERLOAD or VBUS OFF state high. */
|
||||
BOOL Vbus_power(BOOL action) {
|
||||
// power on/off successful
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* probe bus to determine device presense and speed */
|
||||
void MAX_busprobe(void) {
|
||||
BYTE bus_sample;
|
||||
|
||||
// MAXreg_wr(rHCTL,bmSAMPLEBUS);
|
||||
bus_sample = MAXreg_rd( rHRSL); //Get J,K status
|
||||
bus_sample &= ( bmJSTATUS | bmKSTATUS); //zero the rest of the byte
|
||||
|
||||
switch (bus_sample) { //start full-speed or low-speed host
|
||||
case ( bmJSTATUS):
|
||||
/*kludgy*/
|
||||
if (usb_task_state != USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE) { //bus reset causes connection detect interrupt
|
||||
if (!(MAXreg_rd( rMODE) & bmLOWSPEED)) {
|
||||
MAXreg_wr( rMODE, MODE_FS_HOST); //start full-speed host
|
||||
//printf("Starting in full speed\n");
|
||||
} else {
|
||||
MAXreg_wr( rMODE, MODE_LS_HOST); //start low-speed host
|
||||
//printf("Starting in low speed\n");
|
||||
}
|
||||
usb_task_state = ( USB_STATE_ATTACHED); //signal usb state machine to start attachment sequence
|
||||
}
|
||||
break;
|
||||
case ( bmKSTATUS):
|
||||
if (usb_task_state != USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE) { //bus reset causes connection detect interrupt
|
||||
if (!(MAXreg_rd( rMODE) & bmLOWSPEED)) {
|
||||
MAXreg_wr( rMODE, MODE_LS_HOST); //start low-speed host
|
||||
//printf("Starting in low speed\n");
|
||||
} else {
|
||||
MAXreg_wr( rMODE, MODE_FS_HOST); //start full-speed host
|
||||
//printf("Starting in full speed\n");
|
||||
}
|
||||
usb_task_state = ( USB_STATE_ATTACHED); //signal usb state machine to start attachment sequence
|
||||
}
|
||||
break;
|
||||
case ( bmSE1): //illegal state
|
||||
usb_task_state = ( USB_DETACHED_SUBSTATE_ILLEGAL);
|
||||
break;
|
||||
case ( bmSE0): //disconnected state
|
||||
if (!((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED)) //if we came here from other than detached state
|
||||
usb_task_state = ( USB_DETACHED_SUBSTATE_INITIALIZE); //clear device data structures
|
||||
else {
|
||||
MAXreg_wr( rMODE, MODE_FS_HOST); //start full-speed host
|
||||
usb_task_state = ( USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE);
|
||||
}
|
||||
break;
|
||||
} //end switch( bus_sample )
|
||||
}
|
||||
/* MAX3421E initialization after power-on */
|
||||
void MAX3421E_init(void) {
|
||||
/* Configure full-duplex SPI, interrupt pulse */
|
||||
MAXreg_wr( rPINCTL, (bmFDUPSPI + bmINTLEVEL + bmGPXB)); //Full-duplex SPI, level interrupt, GPX
|
||||
MAX3421E_reset(); //stop/start the oscillator
|
||||
/* configure power switch */
|
||||
Vbus_power( OFF); //turn Vbus power off
|
||||
MAXreg_wr( rGPINIEN, bmGPINIEN7); //enable interrupt on GPIN7 (power switch overload flag)
|
||||
Vbus_power( ON);
|
||||
/* configure host operation */
|
||||
MAXreg_wr( rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST | bmSEPIRQ); // set pull-downs, SOF, Host, Separate GPIN IRQ on GPX
|
||||
//MAXreg_wr( rHIEN, bmFRAMEIE|bmCONDETIE|bmBUSEVENTIE ); // enable SOF, connection detection, bus event IRQs
|
||||
MAXreg_wr( rHIEN, bmCONDETIE); //connection detection
|
||||
/* HXFRDNIRQ is checked in Dispatch packet function */
|
||||
MAXreg_wr(rHCTL, bmSAMPLEBUS); // update the JSTATUS and KSTATUS bits
|
||||
MAX_busprobe(); //check if anything is connected
|
||||
MAXreg_wr( rHIRQ, bmCONDETIRQ); //clear connection detect interrupt
|
||||
MAXreg_wr( rCPUCTL, 0x01); //enable interrupt pin
|
||||
}
|
||||
|
||||
/* MAX3421 state change task and interrupt handler */
|
||||
void MAX3421E_Task(void) {
|
||||
if ((*usb_gpio & USB_GPIO_IRQ) == 0) {
|
||||
//printf("MAX interrupt\n\r");
|
||||
MaxIntHandler();
|
||||
}
|
||||
if ((*usb_gpio & USB_GPIO_GPX) != 0) {
|
||||
//printf("GPX interrupt\n\r");
|
||||
MaxGpxHandler();
|
||||
}
|
||||
}
|
||||
|
||||
void MaxIntHandler(void) {
|
||||
BYTE HIRQ;
|
||||
BYTE HIRQ_sendback = 0x00;
|
||||
HIRQ = MAXreg_rd( rHIRQ); //determine interrupt source
|
||||
//printf("IRQ: %x\n", HIRQ);
|
||||
if (HIRQ & bmFRAMEIRQ) { //->1ms SOF interrupt handler
|
||||
HIRQ_sendback |= bmFRAMEIRQ;
|
||||
} //end FRAMEIRQ handling
|
||||
|
||||
if (HIRQ & bmCONDETIRQ) {
|
||||
MAX_busprobe();
|
||||
HIRQ_sendback |= bmCONDETIRQ; //set sendback to 1 to clear register
|
||||
}
|
||||
if (HIRQ & bmSNDBAVIRQ) //if the send buffer is clear (previous transfer completed without issue)
|
||||
{
|
||||
MAXreg_wr(rSNDBC, 0x00);//clear the send buffer (not really necessary, but clears interrupt)
|
||||
}
|
||||
if (HIRQ & bmBUSEVENTIRQ) { //bus event is either reset or suspend
|
||||
usb_task_state++; //advance USB task state machine
|
||||
HIRQ_sendback |= bmBUSEVENTIRQ;
|
||||
}
|
||||
/* End HIRQ interrupts handling, clear serviced IRQs */
|
||||
MAXreg_wr( rHIRQ, HIRQ_sendback); //write '1' to CONDETIRQ to ack bus state change
|
||||
}
|
||||
|
||||
void MaxGpxHandler(void) {
|
||||
BYTE GPINIRQ;
|
||||
GPINIRQ = MAXreg_rd( rGPINIRQ); //read both IRQ registers
|
||||
}
|
||||
@@ -1,250 +0,0 @@
|
||||
/* MAX3421E support header */
|
||||
/* Register names and bit masks for MAX3421 in host mode */
|
||||
/* Function prototypes in MAX3421E.c */
|
||||
#ifndef _MAX3421E_H_
|
||||
#define _MAX3421E_H_
|
||||
|
||||
#define USB_GPIO_RST (1 << 0)
|
||||
#define USB_GPIO_IRQ (1 << 1)
|
||||
#define USB_GPIO_GPX (1 << 2)
|
||||
|
||||
/* SPI interface definitions */
|
||||
/* SSPSTAT REGISTER */
|
||||
|
||||
// Master SPI mode only
|
||||
#define SMPEND 0x80 // Input data sample at end of data out
|
||||
#define SMPMID 0x00 // Input data sample at middle of data out
|
||||
|
||||
#define MODE_00 0 // Setting for SPI bus Mode 0,0
|
||||
//CKE 0x40 // SSPSTAT register
|
||||
//CKP 0x00 // SSPCON1 register
|
||||
|
||||
#define MODE_01 1 // Setting for SPI bus Mode 0,1
|
||||
//CKE 0x00 // SSPSTAT register
|
||||
//CKP 0x00 // SSPCON1 register
|
||||
|
||||
#define MODE_10 2 // Setting for SPI bus Mode 1,0
|
||||
//CKE 0x40 // SSPSTAT register
|
||||
//CKP 0x10 // SSPCON1 register
|
||||
|
||||
#define MODE_11 3 // Setting for SPI bus Mode 1,1
|
||||
//CKE 0x00 // SSPSTAT register
|
||||
//CKP 0x10 // SSPCON1 register
|
||||
|
||||
/* SSPCON1 REGISTER */
|
||||
#define SSPENB 0x20 // Enable serial port and configures SCK, SDO, SDI
|
||||
|
||||
#define SPI_FOSC_4 0 // SPI Master mode, clock = Fosc/4
|
||||
#define SPI_FOSC_16 1 // SPI Master mode, clock = Fosc/16
|
||||
#define SPI_FOSC_64 2 // SPI Master mode, clock = Fosc/64
|
||||
#define SPI_FOSC_TMR2 3 // SPI Master mode, clock = TMR2 output/2
|
||||
#define SLV_SSON 4 // SPI Slave mode, /SS pin control enabled
|
||||
#define SLV_SSOFF 5 // SPI Slave mode, /SS pin control disabled
|
||||
|
||||
/* MAX3421E command byte format: rrrrr0wa where 'r' is register number */
|
||||
//
|
||||
// MAX3421E Registers in HOST mode.
|
||||
//
|
||||
#define rRCVFIFO 0x08 //1<<3
|
||||
#define rSNDFIFO 0x10 //2<<3
|
||||
#define rSUDFIFO 0x20 //4<<3
|
||||
#define rRCVBC 0x30 //6<<3
|
||||
#define rSNDBC 0x38 //7<<3
|
||||
|
||||
#define rUSBIRQ 0x68 //13<<3
|
||||
/* USBIRQ Bits */
|
||||
#define bmVBUSIRQ 0x40 //b6
|
||||
#define bmNOVBUSIRQ 0x20 //b5
|
||||
#define bmOSCOKIRQ 0x01 //b0
|
||||
|
||||
#define rUSBIEN 0x70 //14<<3
|
||||
/* USBIEN Bits */
|
||||
#define bmVBUSIE 0x40 //b6
|
||||
#define bmNOVBUSIE 0x20 //b5
|
||||
#define bmOSCOKIE 0x01 //b0
|
||||
|
||||
#define rUSBCTL 0x78 //15<<3
|
||||
/* USBCTL Bits */
|
||||
#define bmCHIPRES 0x20 //b5
|
||||
#define bmPWRDOWN 0x10 //b4
|
||||
|
||||
#define rCPUCTL 0x80 //16<<3
|
||||
/* CPUCTL Bits */
|
||||
#define bmPUSLEWID1 0x80 //b7
|
||||
#define bmPULSEWID0 0x40 //b6
|
||||
#define bmIE 0x01 //b0
|
||||
|
||||
#define rPINCTL 0x88 //17<<3
|
||||
/* PINCTL Bits */
|
||||
#define bmFDUPSPI 0x10 //b4
|
||||
#define bmINTLEVEL 0x08 //b3
|
||||
#define bmPOSINT 0x04 //b2
|
||||
#define bmGPXB 0x02 //b1
|
||||
#define bmGPXA 0x01 //b0
|
||||
// GPX pin selections
|
||||
#define GPX_OPERATE 0x00
|
||||
#define GPX_VBDET 0x01
|
||||
#define GPX_BUSACT 0x02
|
||||
#define GPX_SOF 0x03
|
||||
|
||||
#define rREVISION 0x90 //18<<3
|
||||
|
||||
#define rIOPINS1 0xa0 //20<<3
|
||||
|
||||
/* IOPINS1 Bits */
|
||||
#define bmGPOUT0 0x01
|
||||
#define bmGPOUT1 0x02
|
||||
#define bmGPOUT2 0x04
|
||||
#define bmGPOUT3 0x08
|
||||
#define bmGPIN0 0x10
|
||||
#define bmGPIN1 0x20
|
||||
#define bmGPIN2 0x40
|
||||
#define bmGPIN3 0x80
|
||||
|
||||
#define rIOPINS2 0xa8 //21<<3
|
||||
/* IOPINS2 Bits */
|
||||
#define bmGPOUT4 0x01
|
||||
#define bmGPOUT5 0x02
|
||||
#define bmGPOUT6 0x04
|
||||
#define bmGPOUT7 0x08
|
||||
#define bmGPIN4 0x10
|
||||
#define bmGPIN5 0x20
|
||||
#define bmGPIN6 0x40
|
||||
#define bmGPIN7 0x80
|
||||
|
||||
#define rGPINIRQ 0xb0 //22<<3
|
||||
/* GPINIRQ Bits */
|
||||
#define bmGPINIRQ0 0x01
|
||||
#define bmGPINIRQ1 0x02
|
||||
#define bmGPINIRQ2 0x04
|
||||
#define bmGPINIRQ3 0x08
|
||||
#define bmGPINIRQ4 0x10
|
||||
#define bmGPINIRQ5 0x20
|
||||
#define bmGPINIRQ6 0x40
|
||||
#define bmGPINIRQ7 0x80
|
||||
|
||||
#define rGPINIEN 0xb8 //23<<3
|
||||
/* GPINIEN Bits */
|
||||
#define bmGPINIEN0 0x01
|
||||
#define bmGPINIEN1 0x02
|
||||
#define bmGPINIEN2 0x04
|
||||
#define bmGPINIEN3 0x08
|
||||
#define bmGPINIEN4 0x10
|
||||
#define bmGPINIEN5 0x20
|
||||
#define bmGPINIEN6 0x40
|
||||
#define bmGPINIEN7 0x80
|
||||
|
||||
#define rGPINPOL 0xc0 //24<<3
|
||||
/* GPINPOL Bits */
|
||||
#define bmGPINPOL0 0x01
|
||||
#define bmGPINPOL1 0x02
|
||||
#define bmGPINPOL2 0x04
|
||||
#define bmGPINPOL3 0x08
|
||||
#define bmGPINPOL4 0x10
|
||||
#define bmGPINPOL5 0x20
|
||||
#define bmGPINPOL6 0x40
|
||||
#define bmGPINPOL7 0x80
|
||||
|
||||
#define rHIRQ 0xc8 //25<<3
|
||||
/* HIRQ Bits */
|
||||
#define bmBUSEVENTIRQ 0x01 // indicates BUS Reset Done or BUS Resume
|
||||
#define bmRWUIRQ 0x02
|
||||
#define bmRCVDAVIRQ 0x04
|
||||
#define bmSNDBAVIRQ 0x08
|
||||
#define bmSUSDNIRQ 0x10
|
||||
#define bmCONDETIRQ 0x20
|
||||
#define bmFRAMEIRQ 0x40
|
||||
#define bmHXFRDNIRQ 0x80
|
||||
|
||||
#define rHIEN 0xd0 //26<<3
|
||||
/* HIEN Bits */
|
||||
#define bmBUSEVENTIE 0x01
|
||||
#define bmRWUIE 0x02
|
||||
#define bmRCVDAVIE 0x04
|
||||
#define bmSNDBAVIE 0x08
|
||||
#define bmSUSDNIE 0x10
|
||||
#define bmCONDETIE 0x20
|
||||
#define bmFRAMEIE 0x40
|
||||
#define bmHXFRDNIE 0x80
|
||||
|
||||
#define rMODE 0xd8 //27<<3
|
||||
/* MODE Bits */
|
||||
#define bmHOST 0x01
|
||||
#define bmLOWSPEED 0x02
|
||||
#define bmHUBPRE 0x04
|
||||
#define bmSOFKAENAB 0x08
|
||||
#define bmSEPIRQ 0x10
|
||||
#define bmDELAYISO 0x20
|
||||
#define bmDMPULLDN 0x40
|
||||
#define bmDPPULLDN 0x80
|
||||
|
||||
#define rPERADDR 0xe0 //28<<3
|
||||
|
||||
#define rHCTL 0xe8 //29<<3
|
||||
/* HCTL Bits */
|
||||
#define bmBUSRST 0x01
|
||||
#define bmFRMRST 0x02
|
||||
#define bmSAMPLEBUS 0x04
|
||||
#define bmSIGRSM 0x08
|
||||
#define bmRCVTOG0 0x10
|
||||
#define bmRCVTOG1 0x20
|
||||
#define bmSNDTOG0 0x40
|
||||
#define bmSNDTOG1 0x80
|
||||
|
||||
#define rHXFR 0xf0 //30<<3
|
||||
/* Host transfer token values for writing the HXFR register (R30) */
|
||||
/* OR this bit field with the endpoint number in bits 3:0 */
|
||||
#define tokSETUP 0x10 // HS=0, ISO=0, OUTNIN=0, SETUP=1
|
||||
#define tokIN 0x00 // HS=0, ISO=0, OUTNIN=0, SETUP=0
|
||||
#define tokOUT 0x20 // HS=0, ISO=0, OUTNIN=1, SETUP=0
|
||||
#define tokINHS 0x80 // HS=1, ISO=0, OUTNIN=0, SETUP=0
|
||||
#define tokOUTHS 0xA0 // HS=1, ISO=0, OUTNIN=1, SETUP=0
|
||||
#define tokISOIN 0x40 // HS=0, ISO=1, OUTNIN=0, SETUP=0
|
||||
#define tokISOOUT 0x60 // HS=0, ISO=1, OUTNIN=1, SETUP=0
|
||||
|
||||
#define rHRSL 0xf8 //31<<3
|
||||
/* HRSL Bits */
|
||||
#define bmRCVTOGRD 0x10
|
||||
#define bmSNDTOGRD 0x20
|
||||
#define bmKSTATUS 0x40
|
||||
#define bmJSTATUS 0x80
|
||||
#define bmSE0 0x00 //SE0 - disconnect state
|
||||
#define bmSE1 0xc0 //SE1 - illegal state
|
||||
/* Host error result codes, the 4 LSB's in the HRSL register */
|
||||
#define hrSUCCESS 0x00
|
||||
#define hrBUSY 0x01
|
||||
#define hrBADREQ 0x02
|
||||
#define hrUNDEF 0x03
|
||||
#define hrNAK 0x04
|
||||
#define hrSTALL 0x05
|
||||
#define hrTOGERR 0x06
|
||||
#define hrWRONGPID 0x07
|
||||
#define hrBADBC 0x08
|
||||
#define hrPIDERR 0x09
|
||||
#define hrPKTERR 0x0A
|
||||
#define hrCRCERR 0x0B
|
||||
#define hrKERR 0x0C
|
||||
#define hrJERR 0x0D
|
||||
#define hrTIMEOUT 0x0E
|
||||
#define hrBABBLE 0x0F
|
||||
|
||||
#define MODE_FS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB)
|
||||
#define MODE_LS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB)
|
||||
|
||||
/* MAX3421E.c function prototypes */
|
||||
void SPI_init(BYTE sync_mode, BYTE bus_mode, BYTE smp_phase);
|
||||
BYTE SPI_wr(BYTE data);
|
||||
void MAXreg_wr(BYTE reg, BYTE val);
|
||||
BYTE* MAXbytes_wr(BYTE reg, BYTE nbytes, BYTE * data);
|
||||
BYTE MAXreg_rd(BYTE reg);
|
||||
BYTE* MAXbytes_rd(BYTE reg, BYTE nbytes, BYTE *data);
|
||||
void MAX3421E_reset(void);
|
||||
BOOL Vbus_power(BOOL action);
|
||||
void MAX3421E_init(void);
|
||||
void MAX_busprobe(void);
|
||||
void MAX3421E_Task(void);
|
||||
void MaxIntHandler(void);
|
||||
void MaxGpxHandler(void);
|
||||
|
||||
#endif //_MAX3421E_H_
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
This is a project directory of Lightweight USB host for Microchip PIC18 and Maxim MAX3421E USB Host controller.
|
||||
This is a migration from FreeRTOS implementation, which I decided to stop developing because the end product will not fit into PIC18.
|
||||
Therefore, you will find fragments of strange code every now and then.
|
||||
|
||||
The code is compiled using Microchip C18 compiler in MPLAB. MPLAB project file is provided but not guaranteed to work on your system
|
||||
due to absolute path issue. You can manually edit the .mcp file or make your own. The project uses standard linker script and headers.
|
||||
|
||||
In addition, logic analyzer trace is provided in LPF file. Too see the trace you will need to download Logicport software from Intronix,
|
||||
http://www.pctestinstruments.com/downloads.htm
|
||||
|
||||
For hardware implementation information go to http://www.circuitsathome.com
|
||||
|
||||
277
sw/usb/USB.h
277
sw/usb/USB.h
@@ -1,277 +0,0 @@
|
||||
/* USB task support header */
|
||||
|
||||
#ifndef _USB_h_
|
||||
#define _USB_h_
|
||||
|
||||
// *****************************************************************************
|
||||
// Section: State Machine Constants
|
||||
// *****************************************************************************
|
||||
|
||||
/* States are defined by 4 high bits
|
||||
Substates are defined by 4 low bits */
|
||||
|
||||
#define USB_STATE_MASK 0xf0 //
|
||||
#define USB_SUBSTATE_MASK 0x0f //
|
||||
|
||||
#define SUBSUBSTATE_MASK 0x000F //
|
||||
|
||||
#define NEXT_STATE 0x0100 //
|
||||
#define NEXT_SUBSTATE 0x0010 //
|
||||
#define NEXT_SUBSUBSTATE 0x0001 //
|
||||
|
||||
#define SUBSUBSTATE_ERROR 0x000F //
|
||||
|
||||
#define NO_STATE 0xFFFF //
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
DETACHED state machine values
|
||||
|
||||
This state machine handles the condition when no device is attached.
|
||||
*/
|
||||
|
||||
#define USB_STATE_DETACHED 0x00
|
||||
#define USB_DETACHED_SUBSTATE_INITIALIZE 0x01
|
||||
#define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x03
|
||||
#define USB_DETACHED_SUBSTATE_ILLEGAL 0x04
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
ATTACHED state machine values
|
||||
|
||||
This state machine gets the device descriptor of the remote device. We get the
|
||||
size of the device descriptor, and use that size to get the entire device
|
||||
descriptor. Then we check the VID and PID and make sure they appear in the TPL.
|
||||
*/
|
||||
|
||||
#define USB_STATE_ATTACHED 0x10
|
||||
#define USB_ATTACHED_SUBSTATE_SETTLE 0x11
|
||||
#define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x12
|
||||
#define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x13
|
||||
#define USB_ATTACHED_SUBSTATE_WAIT_SOF 0x14
|
||||
#define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x15
|
||||
//#define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR 0x16
|
||||
//#define USB_ATTACHED_SUBSTATE_VALIDATE_VID_PID 0x17
|
||||
//#define USB_ATTACHED_SUBSTATE_VALIDATE_CLSP 0x18
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
ADDRESSING state machine values
|
||||
|
||||
This state machine sets the address of the remote device.
|
||||
*/
|
||||
|
||||
#define USB_STATE_ADDRESSING 0x20
|
||||
/*
|
||||
*******************************************************************************
|
||||
CONFIGURING state machine values
|
||||
|
||||
This state machine sets the configuration of the remote device, and sets up
|
||||
internal variables to support the device.
|
||||
*/
|
||||
#define USB_STATE_CONFIGURING 0x30
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
RUNNING state machine values
|
||||
|
||||
*/
|
||||
|
||||
#define USB_STATE_RUNNING 0x40
|
||||
//#define RUNNING_SUBSTATE_NORMAL_RUN 0x0000 //
|
||||
//#define RUNNING_SUBSTATE_SUSPEND_AND_RESUME 0x0010 //
|
||||
//#define RUNNING_SUBSUBSTATE_SUSPEND 0x0000 //
|
||||
//#define RUNNING_SUBSUBSTATE_RESUME 0x0001 //
|
||||
//#define RUNNING_SUBSUBSTATE_RESUME_WAIT 0x0002 //
|
||||
//#define RUNNING_SUBSUBSTATE_RESUME_RECOVERY 0x0003 //
|
||||
//#define RUNNING_SUBSUBSTATE_RESUME_RECOVERY_WAIT 0x0004 //
|
||||
//#define RUNNING_SUBSUBSTATE_RESUME_COMPLETE 0x0005 //
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
HOLDING state machine values
|
||||
|
||||
*/
|
||||
|
||||
#define STATE_HOLDING 0x50 //
|
||||
|
||||
#define HOLDING_SUBSTATE_HOLD_INIT 0x0000 //
|
||||
#define HOLDING_SUBSTATE_HOLD 0x0001 //
|
||||
|
||||
/* Error state machine state. Non-recoverable */
|
||||
|
||||
#define USB_STATE_ERROR 0xff
|
||||
|
||||
// *****************************************************************************
|
||||
// Section: Token State Machine Constants
|
||||
// *****************************************************************************
|
||||
|
||||
#define TSTATE_MASK 0x00F0 //
|
||||
#define TSUBSTATE_MASK 0x000F //
|
||||
|
||||
#define TSUBSTATE_ERROR 0x000F //
|
||||
|
||||
#define TSTATE_IDLE 0x0000 //
|
||||
|
||||
#define TSTATE_CONTROL_NO_DATA 0x0010 //
|
||||
#define TSUBSTATE_CONTROL_NO_DATA_SETUP 0x0000 //
|
||||
#define TSUBSTATE_CONTROL_NO_DATA_ACK 0x0001 //
|
||||
#define TSUBSTATE_CONTROL_NO_DATA_COMPLETE 0x0002 //
|
||||
|
||||
#define TSTATE_CONTROL_READ 0x0020 //
|
||||
#define TSUBSTATE_CONTROL_READ_SETUP 0x0000 //
|
||||
#define TSUBSTATE_CONTROL_READ_DATA 0x0001 //
|
||||
#define TSUBSTATE_CONTROL_READ_ACK 0x0002 //
|
||||
#define TSUBSTATE_CONTROL_READ_COMPLETE 0x0003 //
|
||||
|
||||
#define TSTATE_CONTROL_WRITE 0x0030 //
|
||||
#define TSUBSTATE_CONTROL_WRITE_SETUP 0x0000 //
|
||||
#define TSUBSTATE_CONTROL_WRITE_DATA 0x0001 //
|
||||
#define TSUBSTATE_CONTROL_WRITE_ACK 0x0002 //
|
||||
#define TSUBSTATE_CONTROL_WRITE_COMPLETE 0x0003 //
|
||||
|
||||
#define TSTATE_INTERRUPT_READ 0x0040 //
|
||||
#define TSUBSTATE_INTERRUPT_READ_DATA 0x0000 //
|
||||
#define TSUBSTATE_INTERRUPT_READ_COMPLETE 0x0001 //
|
||||
|
||||
#define TSTATE_INTERRUPT_WRITE 0x0050 //
|
||||
#define TSUBSTATE_INTERRUPT_WRITE_DATA 0x0000 //
|
||||
#define TSUBSTATE_INTERRUPT_WRITE_COMPLETE 0x0001 //
|
||||
|
||||
#define TSTATE_ISOCHRONOUS_READ 0x0060 //
|
||||
#define TSUBSTATE_ISOCHRONOUS_READ_DATA 0x0000 //
|
||||
#define TSUBSTATE_ISOCHRONOUS_READ_COMPLETE 0x0001 //
|
||||
|
||||
#define TSTATE_ISOCHRONOUS_WRITE 0x0070 //
|
||||
#define TSUBSTATE_ISOCHRONOUS_WRITE_DATA 0x0000 //
|
||||
#define TSUBSTATE_ISOCHRONOUS_WRITE_COMPLETE 0x0001 //
|
||||
|
||||
#define TSTATE_BULK_READ 0x0080 //
|
||||
#define TSUBSTATE_BULK_READ_DATA 0x0000 //
|
||||
#define TSUBSTATE_BULK_READ_COMPLETE 0x0001 //
|
||||
|
||||
#define TSTATE_BULK_WRITE 0x0090 //
|
||||
#define TSUBSTATE_BULK_WRITE_DATA 0x0000 //
|
||||
#define TSUBSTATE_BULK_WRITE_COMPLETE 0x0001 //
|
||||
|
||||
// ************************
|
||||
// Standard USB Requests
|
||||
#define SR_GET_STATUS 0x00 // Get Status
|
||||
#define SR_CLEAR_FEATURE 0x01 // Clear Feature
|
||||
#define SR_RESERVED 0x02 // Reserved
|
||||
#define SR_SET_FEATURE 0x03 // Set Feature
|
||||
#define SR_SET_ADDRESS 0x05 // Set Address
|
||||
#define SR_GET_DESCRIPTOR 0x06 // Get Descriptor
|
||||
#define SR_SET_DESCRIPTOR 0x07 // Set Descriptor
|
||||
#define SR_GET_CONFIGURATION 0x08 // Get Configuration
|
||||
#define SR_SET_CONFIGURATION 0x09 // Set Configuration
|
||||
#define SR_GET_INTERFACE 0x0a // Get Interface
|
||||
#define SR_SET_INTERFACE 0x0b // Set Interface
|
||||
|
||||
// Get Descriptor codes
|
||||
#define GD_DEVICE 0x01 // Get device descriptor: Device
|
||||
#define GD_CONFIGURATION 0x02 // Get device descriptor: Configuration
|
||||
#define GD_STRING 0x03 // Get device descriptor: String
|
||||
#define GD_HID 0x21 // Get descriptor: HID
|
||||
#define GD_REPORT 0x22 // Get descriptor: Report
|
||||
|
||||
// HID bRequest values
|
||||
#define GET_REPORT 1
|
||||
#define GET_IDLE 2
|
||||
#define GET_PROTOCOL 3
|
||||
#define SET_REPORT 9
|
||||
#define SET_IDLE 0x0A
|
||||
#define SET_PROTOCOL 0x0B
|
||||
#define INPUT_REPORT 1
|
||||
|
||||
////******************************************************************************
|
||||
////******************************************************************************
|
||||
//// Section: Macros
|
||||
////
|
||||
//// These macros are all internal to the host layer.
|
||||
////******************************************************************************
|
||||
////******************************************************************************
|
||||
//
|
||||
//#define _USB_InitErrorCounters() { numCommandTries = USB_NUM_COMMAND_TRIES; }
|
||||
//#define _USB_SetDATA01(x) { pCurrentEndpoint->status.bfNextDATA01 = x; }
|
||||
//#define _USB_SetErrorCode(x) { usbDeviceInfo.errorCode = x; }
|
||||
//#define _USB_SetHoldState() { usbHostState = STATE_HOLDING; }
|
||||
//#define _USB_SetNextState() { usbHostState = (usbHostState & STATE_MASK) + NEXT_STATE; }
|
||||
//#define _host_tasks_SetNextSubState() { host_tasks_state =( host_tasks_state & (STATE_MASK | SUBSTATE_MASK)) + NEXT_SUBSTATE; }
|
||||
//#define _USB_SetNextSubSubState() { usbHostState = usbHostState + NEXT_SUBSUBSTATE; }
|
||||
//#define _USB_SetNextTransferState() { pCurrentEndpoint->transferState ++; }
|
||||
//#define _USB_SetPreviousSubSubState() { usbHostState = usbHostState - NEXT_SUBSUBSTATE; }
|
||||
//#define _USB_SetTransferErrorState(x) { x->transferState = (x->transferState & TSTATE_MASK) | TSUBSTATE_ERROR; }
|
||||
//#define freez(x) { free(x); x = NULL; }
|
||||
|
||||
/* data structures */
|
||||
|
||||
// *****************************************************************************
|
||||
/* USB Mass Storage Device Information
|
||||
|
||||
This structure is used to hold all the information about an attached Mass Storage device.
|
||||
*/
|
||||
typedef struct _USB_MSD_DEVICE_INFO {
|
||||
BYTE blockData[31]; // Data buffer for device communication.
|
||||
BYTE deviceAddress; // Address of the device on the bus.
|
||||
BYTE errorCode; // Error code of last error.
|
||||
BYTE state; // State machine state of the device.
|
||||
BYTE returnState; // State to return to after performing error handling.
|
||||
union {
|
||||
struct {
|
||||
unsigned int bfDirection :1; // Direction of current transfer (0=OUT, 1=IN).
|
||||
unsigned int bfReset :1; // Flag indicating to perform Mass Storage Reset.
|
||||
unsigned int bfClearDataIN :1; // Flag indicating to clear the IN endpoint.
|
||||
unsigned int bfClearDataOUT :1; // Flag indicating to clear the OUT endpoint.
|
||||
};
|
||||
BYTE val;
|
||||
} flags;
|
||||
BYTE maxLUN; // The maximum Logical Unit Number of the device.
|
||||
BYTE interface; // Interface number we are using.
|
||||
BYTE epin_idx; // Bulk IN endpoint index in devinfo.epinfo_ptr[].
|
||||
BYTE epout_idx; // Bulk OUT endpoint index in devinfo.epinfo_ptr[].
|
||||
BYTE endpointDATA; // Endpoint to use for the current transfer.
|
||||
BYTE *userData; // Pointer to the user's data buffer.
|
||||
DWORD userDataLength; // Length of the user's data buffer.
|
||||
DWORD bytesTransferred; // Number of bytes transferred to/from the user's data buffer.
|
||||
DWORD dCBWTag; // The value of the dCBWTag to verify against the dCSWtag.
|
||||
BYTE attemptsCSW; // Number of attempts to retrieve the CSW.
|
||||
} USB_MSD_DEVICE_INFO;
|
||||
|
||||
///* class driver event handler */
|
||||
//typedef BOOL (* rom CLASS_EVENT_HANDLER) ( BYTE address, BYTE event, void *data, DWORD size );
|
||||
//
|
||||
///* class driver initialization */
|
||||
//typedef BOOL (* rom CLASS_INIT) ( BYTE address, DWORD flags );
|
||||
//
|
||||
//// *****************************************************************************
|
||||
///* Client Driver Table Structure
|
||||
//
|
||||
// */
|
||||
//
|
||||
//typedef struct _CLASS_CALLBACK_TABLE
|
||||
//{
|
||||
// CLASS_INIT Initialize; // Initialization routine
|
||||
// CLASS_EVENT_HANDLER EventHandler; // Event routine
|
||||
// DWORD flags; // Initialization flags
|
||||
//
|
||||
//} CLASS_CALLBACK_TABLE;
|
||||
|
||||
//* Functions */
|
||||
//
|
||||
//void vUSBtask_init( void );
|
||||
//void vUSB_task( void *pvParameters );
|
||||
//void prvUSBdata_init( void );
|
||||
//char bUSB_Control_Write_ND( BYTE addr, BYTE ep );
|
||||
//char bUSB_Control_Read( BYTE addr, BYTE ep );
|
||||
//char bUSB_IN_Transfer( BYTE ep, WORD nbytes, BYTE maxpktsize, BYTE * data );
|
||||
//char bUSB_Dispatch_Pkt( BYTE token, BYTE ep );
|
||||
//BOOL prvMSDInit( BYTE address, DWORD flags );
|
||||
//BOOL prvMSDEventHandler( BYTE address, BYTE event, void *data, DWORD size );
|
||||
//BOOL prvCDCProbe( BYTE address, DWORD flags );
|
||||
//BOOL prvCDCEventHandler( BYTE address, BYTE event, void *data, DWORD size );
|
||||
//BOOL prvDummyProbe( BYTE address , DWORD flags );
|
||||
//BOOL prvDummyEventHandler( BYTE address, BYTE event, void *data, DWORD size );
|
||||
//BYTE flush_Q( xQueueHandle QueueH );
|
||||
|
||||
#endif //_USB_h_
|
||||
@@ -1,22 +0,0 @@
|
||||
/* Project name project configuration file */
|
||||
|
||||
#ifndef _project_config_h_
|
||||
#define _project_config_h_
|
||||
|
||||
#include "GenericMacros.h"
|
||||
#include "GenericTypeDefs.h"
|
||||
#include "HID.h"
|
||||
#include "MAX3421E.h"
|
||||
#include "transfer.h"
|
||||
#include "usb_ch9.h"
|
||||
#include "USB.h"
|
||||
|
||||
/* USB constants */
|
||||
/* time in milliseconds */
|
||||
#define USB_SETTLE_TIME 200 //USB settle after reset
|
||||
#define USB_XFER_TIMEOUT 5000 //USB transfer timeout
|
||||
|
||||
#define USB_NAK_LIMIT 2
|
||||
#define USB_RETRY_LIMIT 3
|
||||
|
||||
#endif // _project_config_h
|
||||
@@ -1,475 +0,0 @@
|
||||
|
||||
/* USB transfers */
|
||||
#define _transfer_c_
|
||||
|
||||
#include "project_config.h"
|
||||
#include <stdio.h>
|
||||
|
||||
EP_RECORD dev0ep = {{ 0 }}; //Endpoint data structure for uninitialized device during enumeration
|
||||
EP_RECORD msd_ep[ 3 ] = {{ 0 }}; //Mass storage bulk-only transport endpoints: 1 control and 2 bulk, IN and OUT
|
||||
//ep records for other classes are defined in class-specific modules
|
||||
|
||||
/* macros to aid filling in TPL */
|
||||
#define INIT_VID_PID(v,p) 0x##p##v
|
||||
#define INIT_CL_SC_P(c,s,p) 0x##00##p##s##c
|
||||
|
||||
//const rom USB_TPL_ENTRY TplTable[ USB_NUMTARGETS + 1 ] = {
|
||||
//// VID & PID or Client
|
||||
//// Class, Subclass & Protocol Config Numep Eprecord Driver
|
||||
//{ INIT_VID_PID( 0000, 0000 ), 0, 1, &dev0ep, 0, "Uninitialized" },
|
||||
//{ INIT_VID_PID( 0781, 5406 ), 0, 3, msd_ep, MSD_DRIVER, "Mass storage" }, //Sandisk U3 Cruzer Micro
|
||||
////{ INIT_VID_PID( 0CF2, 6220 ), 0, 0 }, //ENE UB6220
|
||||
//{ INIT_CL_SC_P( 03, 01, 02 ), 0, 3, hid_ep, HIDM_DRIVER, "HID Mouse with Boot protocol" }, //
|
||||
//{ INIT_VID_PID( aaaa, 5555 ), 0, 1, NULL, 0, NULL }, //
|
||||
//{ INIT_CL_SC_P( 08, 06, 50 ), 0, 3, msd_ep, MSD_DRIVER, "Mass storage" } //Mass storage bulk only class
|
||||
//};
|
||||
|
||||
/* control transfers function pointers */
|
||||
const CTRL_XFER ctrl_xfers[ 2 ] = {
|
||||
XferCtrlND,
|
||||
XferCtrlData
|
||||
};
|
||||
|
||||
/* device table. Filled during enumeration */
|
||||
/* index corresponds to device address */
|
||||
/* each entry contains pointer to endpoint structure */
|
||||
/* and device class to use in various places */
|
||||
DEV_RECORD devtable[ USB_NUMDEVICES + 1 ];
|
||||
|
||||
/* Client Driver Function Pointer Table */
|
||||
CLASS_CALLBACK_TABLE ClientDriverTable[ USB_NUMCLASSES ] = {
|
||||
{
|
||||
MSDProbe, //Mass storage class device init
|
||||
MSDEventHandler,
|
||||
0
|
||||
},
|
||||
{
|
||||
HIDMProbe, //HID class device init
|
||||
HIDMEventHandler,
|
||||
0
|
||||
},
|
||||
{
|
||||
HIDKProbe,
|
||||
HIDKEventHandler,
|
||||
0
|
||||
},
|
||||
{
|
||||
DummyProbe,
|
||||
DummyEventHandler,
|
||||
0
|
||||
}
|
||||
};
|
||||
/* Control transfer stages function pointer table */
|
||||
|
||||
|
||||
/* USB state machine related variables */
|
||||
|
||||
BYTE usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
|
||||
BYTE usb_error;
|
||||
BYTE last_usb_task_state = 0;
|
||||
|
||||
/* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer, */
|
||||
/* depending on request. Actual requests are defined as macros */
|
||||
/* return codes: */
|
||||
/* 00 = success */
|
||||
/* 01-0f = non-zero HRSLT */
|
||||
BYTE XferCtrlReq( BYTE addr, BYTE ep, BYTE bmReqType, BYTE bRequest, BYTE wValLo, BYTE wValHi, WORD wInd, WORD nbytes, BYTE* dataptr )
|
||||
{
|
||||
BOOL direction = FALSE; //request direction, IN or OUT
|
||||
BYTE datastage = 1; //request data stage present or absent
|
||||
BYTE rcode;
|
||||
SETUP_PKT setup_pkt;
|
||||
if( dataptr == NULL ) {
|
||||
datastage = 0;
|
||||
}
|
||||
MAXreg_wr( rPERADDR, addr ); //set peripheral address
|
||||
/* fill in setup packet */
|
||||
if( bmReqType & 0x80 ) {
|
||||
direction = TRUE; //determine request direction
|
||||
}
|
||||
/* fill in setup packet */
|
||||
setup_pkt.ReqType_u.bmRequestType = bmReqType;
|
||||
setup_pkt.bRequest = bRequest;
|
||||
setup_pkt.wVal_u.wValueLo = wValLo;
|
||||
setup_pkt.wVal_u.wValueHi = wValHi;
|
||||
setup_pkt.wIndex = wInd;
|
||||
setup_pkt.wLength = nbytes;
|
||||
MAXbytes_wr( rSUDFIFO, 8, (BYTE *)&setup_pkt ); //transfer to setup packet FIFO
|
||||
rcode = XferDispatchPkt( tokSETUP, ep ); //dispatch packet
|
||||
if( rcode ) { //return HRSLT if not zero
|
||||
return( rcode );
|
||||
}
|
||||
rcode = ctrl_xfers[ datastage ]( addr, ep, nbytes, dataptr, direction ); //call data stage or no data stage transfer
|
||||
return( rcode );
|
||||
}
|
||||
/* Control transfer with data stage */
|
||||
BYTE XferCtrlData( BYTE addr, BYTE ep, WORD nbytes, BYTE* dataptr, BOOL direction )
|
||||
{
|
||||
BYTE rcode;
|
||||
|
||||
//MAXreg_wr( rHCTL, bmRCVTOG1 ); //set toggle to DATA1
|
||||
if( direction ) { //IN transfer
|
||||
devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1;
|
||||
rcode = XferInTransfer( addr, ep, nbytes, dataptr, devtable[ addr ].epinfo[ ep ].MaxPktSize );
|
||||
if( rcode ) {
|
||||
return( rcode );
|
||||
}
|
||||
rcode = XferDispatchPkt( tokOUTHS, ep );
|
||||
return( rcode );
|
||||
}
|
||||
else { //OUT not implemented
|
||||
return( 0xff );
|
||||
}
|
||||
}
|
||||
/* Control transfer with status stage and no data stage */
|
||||
BYTE XferCtrlND( BYTE addr, BYTE ep, WORD nbytes, BYTE* dataptr, BOOL direction )
|
||||
{
|
||||
BYTE rcode;
|
||||
|
||||
(void) addr;
|
||||
(void) nbytes;
|
||||
(void) dataptr;
|
||||
|
||||
if( direction ) { //GET
|
||||
rcode = XferDispatchPkt( tokOUTHS, ep );
|
||||
}
|
||||
else {
|
||||
rcode = XferDispatchPkt( tokINHS, ep );
|
||||
}
|
||||
return( rcode );
|
||||
}
|
||||
/* Dispatch a packet. Assumes peripheral address is set and, if necessary, sudFIFO-sendFIFO loaded. */
|
||||
/* Result code: 0 success, nonzero = error condition */
|
||||
/* If NAK, tries to re-send up to USB_NAK_LIMIT times */
|
||||
/* If bus timeout, re-sends up to USB_RETRY_LIMIT times */
|
||||
/* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */
|
||||
BYTE XferDispatchPkt( BYTE token, BYTE ep )
|
||||
{
|
||||
DWORD timeout = 0;//(alt_nticks()*1000)/alt_ticks_per_second() + USB_XFER_TIMEOUT;
|
||||
BYTE tmpdata;
|
||||
BYTE rcode;
|
||||
char retry_count = 0;
|
||||
BYTE nak_count = 0;
|
||||
|
||||
while( 1 ) {
|
||||
MAXreg_wr( rHXFR, ( token|ep )); //launch the transfer
|
||||
rcode = 0xff;
|
||||
/*
|
||||
while( (alt_nticks()*1000)/alt_ticks_per_second() < timeout ) {
|
||||
tmpdata = MAXreg_rd( rHIRQ );
|
||||
if( tmpdata & bmHXFRDNIRQ ) {
|
||||
MAXreg_wr( rHIRQ, bmHXFRDNIRQ ); //clear the interrupt
|
||||
rcode = 0x00;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
if( rcode != 0x00 ) { //exit if timeout
|
||||
return( rcode );
|
||||
}
|
||||
rcode = ( MAXreg_rd( rHRSL ) & 0x0f );
|
||||
if( rcode == hrNAK ) {
|
||||
nak_count++;
|
||||
if( nak_count == USB_NAK_LIMIT ) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( rcode == hrTIMEOUT ) {
|
||||
retry_count++;
|
||||
if( retry_count == USB_RETRY_LIMIT ) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else break;
|
||||
}//while( 1 )
|
||||
return( rcode );
|
||||
}
|
||||
/* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes.
|
||||
Keep sending INs and writes data to memory area pointed by 'data' */
|
||||
/* rcode 0 if no errors. rcode 01-0f is relayed from prvXferDispatchPkt(). Rcode f0 means RCVDAVIRQ error,
|
||||
fe USB xfer timeout */
|
||||
BYTE XferInTransfer( BYTE addr/* not sure if it's necessary */, BYTE ep, WORD nbytes, BYTE* data, BYTE maxpktsize )
|
||||
{
|
||||
BYTE rcode;
|
||||
//BYTE i;
|
||||
//BYTE tmpbyte;
|
||||
BYTE pktsize;
|
||||
WORD xfrlen = 0;
|
||||
MAXreg_wr( rHCTL, devtable[ addr ].epinfo[ ep ].rcvToggle ); //set toggle value
|
||||
while( 1 ) { // use a 'return' to exit this loop
|
||||
rcode = XferDispatchPkt( tokIN, ep ); //IN packet to EP-'endpoint'. Function takes care of NAKS.
|
||||
if( rcode ) {
|
||||
return( rcode ); //should be 0, indicating ACK. Else return error code.
|
||||
}
|
||||
/* check for RCVDAVIRQ and generate error if not present */
|
||||
/* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */
|
||||
if(( MAXreg_rd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) {
|
||||
return ( 0xf0 ); //receive error
|
||||
}
|
||||
pktsize = MAXreg_rd( rRCVBC ); //number of received bytes
|
||||
//printf ("pktsize: %d\n", pktsize);
|
||||
data = MAXbytes_rd( rRCVFIFO, pktsize, data );
|
||||
MAXreg_wr( rHIRQ, bmRCVDAVIRQ ); // Clear the IRQ & free the buffer
|
||||
xfrlen += pktsize; // add this packet's byte count to total transfer length
|
||||
/* The transfer is complete under two conditions: */
|
||||
/* 1. The device sent a short packet (L.T. maxPacketSize) */
|
||||
/* 2. 'nbytes' have been transferred. */
|
||||
if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) { // have we transferred 'nbytes' bytes?
|
||||
if( MAXreg_rd( rHRSL ) & bmRCVTOGRD ) { //save toggle value
|
||||
devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1;
|
||||
}
|
||||
else {
|
||||
devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG0;
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
}//while( 1 )
|
||||
}
|
||||
/* initialization of USB data structures */
|
||||
void USB_init( void )
|
||||
{
|
||||
BYTE i;
|
||||
for( i = 0; i < ( USB_NUMDEVICES + 1 ); i++ ) {
|
||||
devtable[ i ].epinfo = NULL; //clear device table
|
||||
devtable[ i ].devclass = 0;
|
||||
}
|
||||
devtable[ 0 ].epinfo = &dev0ep; //set single ep for uninitialized device
|
||||
dev0ep.MaxPktSize = 0;
|
||||
dev0ep.sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0
|
||||
dev0ep.rcvToggle = bmRCVTOG0;
|
||||
}
|
||||
|
||||
|
||||
USB_DEVICE_DESCRIPTOR buf = {0};
|
||||
USB_STRING_DESCRIPTOR strDesc = {0};
|
||||
|
||||
/* USB state machine. Connect/disconnect, enumeration, initialization */
|
||||
/* error codes: 01-0f HRSLT */
|
||||
/* ff - unsupported device */
|
||||
/* fe - no address available */
|
||||
/* fd - no client driver available */
|
||||
void USB_Task( void )
|
||||
{
|
||||
static DWORD usb_delay = 0;
|
||||
static BYTE tmp_addr;
|
||||
|
||||
BYTE rcode, tmpdata;
|
||||
BYTE i;
|
||||
|
||||
switch( usb_task_state & USB_STATE_MASK ) {
|
||||
/* Detached state - when nothing is connected to ( or just disconnected from) USB bus */
|
||||
case( USB_STATE_DETACHED ):
|
||||
switch( usb_task_state ) {
|
||||
case( USB_DETACHED_SUBSTATE_INITIALIZE ):
|
||||
/* cleanup device data structures */
|
||||
USB_init();
|
||||
usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
|
||||
break;
|
||||
case( USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE ):
|
||||
/* Do nothing */
|
||||
MAXreg_wr(rHCTL,bmSAMPLEBUS);
|
||||
break;
|
||||
case( USB_DETACHED_SUBSTATE_ILLEGAL ):
|
||||
/* don't know what to do yet */
|
||||
break;
|
||||
}//switch( usb_task_state )
|
||||
break;//( USB_STATE_DETACHED ):
|
||||
/**/
|
||||
case( USB_STATE_ATTACHED ): //prepare for enumeration
|
||||
switch( usb_task_state ) {
|
||||
case( USB_STATE_ATTACHED ):
|
||||
//TODO
|
||||
//usb_delay = (alt_nticks()*1000)/alt_ticks_per_second() + 200; //initial settle 200ms
|
||||
usb_delay = 0;
|
||||
usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
|
||||
break;//case( USB_STATE_ATTACHED )
|
||||
case( USB_ATTACHED_SUBSTATE_SETTLE ): //waiting for settle timer to expire
|
||||
//TODO
|
||||
/*
|
||||
if( (alt_nticks()*1000)/alt_ticks_per_second() > usb_delay ) {
|
||||
usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
|
||||
}
|
||||
*/
|
||||
break;//case( USB_ATTACHED_SUBSTATE_SETTLE )
|
||||
case( USB_ATTACHED_SUBSTATE_RESET_DEVICE ):
|
||||
MAXreg_wr( rHIRQ, bmBUSEVENTIRQ ); //clear bus event IRQ
|
||||
MAXreg_wr( rHCTL, bmBUSRST ); //issue bus reset
|
||||
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
|
||||
break;//case( USB_ATTACHED_SUBSTATE_RESET_DEVICE )
|
||||
case( USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE ): //wait for bus reset and first SOF
|
||||
if(( MAXreg_rd( rHCTL ) & bmBUSRST ) == 0 ) {
|
||||
tmpdata = MAXreg_rd( rMODE ) | bmSOFKAENAB; //start SOF generation
|
||||
MAXreg_wr( rMODE, tmpdata );
|
||||
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
|
||||
}
|
||||
break;//case( USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE )
|
||||
case( USB_ATTACHED_SUBSTATE_WAIT_SOF ):
|
||||
if( MAXreg_rd( rHIRQ ) | bmFRAMEIRQ ) { //when first SOF received we can continue
|
||||
usb_task_state = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
|
||||
}
|
||||
break;//case( USB_ATTACHED_SUBSTATE_WAIT_SOF )
|
||||
case( USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE ): //send request for first 8 bytes of device descriptor
|
||||
devtable[ 0 ].epinfo->MaxPktSize = 0x0008; //fill max packet size with minimum allowed
|
||||
rcode = XferGetDevDescr( 0, 0, 8, (BYTE *)&buf ); //get device descriptor size
|
||||
if( rcode == 0 ) {
|
||||
devtable[ 0 ].epinfo->MaxPktSize = buf.bMaxPacketSize0;
|
||||
|
||||
rcode = XferGetDevDescr( 0, 0, buf.bLength, (BYTE *)&buf ); //get full descriptor
|
||||
//pull the string descriptor for the product if it exists
|
||||
//hackish, store this somewhere
|
||||
if (buf.iManufacturer != 0)
|
||||
{
|
||||
rcode = XferGetStrDescr( 0, 0, 2, buf.iManufacturer, LANG_EN_US, (BYTE *)&strDesc);
|
||||
rcode = XferGetStrDescr( 0, 0, strDesc.bLength, buf.iManufacturer, LANG_EN_US, (BYTE *)&strDesc);
|
||||
//printf ("Mfgr string(%i): %s\n", buf.iManufacturer, ConvUTF8ToStr(strDesc.bString, (strDesc.bLength>>1)-1));
|
||||
}
|
||||
if (buf.iProduct != 0)
|
||||
{
|
||||
rcode = XferGetStrDescr( 0, 0, 2, buf.iProduct, LANG_EN_US, (BYTE *)&strDesc);
|
||||
rcode = XferGetStrDescr( 0, 0, strDesc.bLength, buf.iProduct, LANG_EN_US, (BYTE *)&strDesc);
|
||||
//printf ("Product string(%i): %s\n", buf.iProduct, ConvUTF8ToStr(strDesc.bString, (strDesc.bLength>>1)-1));
|
||||
}
|
||||
usb_task_state = USB_STATE_ADDRESSING;
|
||||
|
||||
}
|
||||
else {
|
||||
usb_error = rcode;
|
||||
last_usb_task_state = usb_task_state;
|
||||
usb_task_state = USB_STATE_ERROR;
|
||||
}
|
||||
break;//case( USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE ):
|
||||
}//switch( usb_task_state )
|
||||
break;//case ( USB_STATE_ATTACHED )
|
||||
case( USB_STATE_ADDRESSING ): //give device an address
|
||||
for( i = 1; i < USB_NUMDEVICES; i++ ) {
|
||||
if( devtable[ i ].epinfo == NULL ) {
|
||||
devtable[ i ].epinfo = devtable[ 0 ].epinfo; //set correct MaxPktSize
|
||||
//devtable[ i ].epinfo->MaxPktSize = devtable[ 0 ].epinfo->MaxPktSize; //copy uninitialized device record to have correct MaxPktSize
|
||||
rcode = XferSetAddr( 0, 0, i );
|
||||
if( rcode == 0 ) {
|
||||
tmp_addr = i;
|
||||
usb_task_state = USB_STATE_CONFIGURING;
|
||||
}
|
||||
else {
|
||||
usb_error = rcode; //set address error
|
||||
last_usb_task_state = usb_task_state;
|
||||
usb_task_state = USB_STATE_ERROR;
|
||||
}
|
||||
break; //break if address assigned or error occurred during address assignment attempt
|
||||
}
|
||||
}
|
||||
if( usb_task_state == USB_STATE_ADDRESSING ) {
|
||||
usb_error = 0xfe;
|
||||
last_usb_task_state = usb_task_state;
|
||||
usb_task_state = USB_STATE_ERROR;
|
||||
}
|
||||
break;//case ( USB_STATE_ADDRESSING )
|
||||
case( USB_STATE_CONFIGURING ): //checking for driver
|
||||
//run device class probes until one returns TRUE
|
||||
for( i = 0; i < USB_NUMCLASSES; i++ ) {
|
||||
rcode = ClientDriverTable[ i ].Initialize( tmp_addr, 0 );
|
||||
if( rcode == TRUE ) {
|
||||
usb_task_state = USB_STATE_RUNNING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( usb_task_state == USB_STATE_CONFIGURING ) {
|
||||
usb_error = 0xfd;
|
||||
last_usb_task_state = usb_task_state;
|
||||
usb_task_state = USB_STATE_ERROR;
|
||||
}
|
||||
break;//( USB_STATE_CONFIGURING )
|
||||
case( USB_STATE_RUNNING ):
|
||||
//vTaskDelay( LED_RATE );
|
||||
break;//( USB_STATE_RUNNING )
|
||||
case( USB_STATE_ERROR ):
|
||||
//vTaskDelay( LED_RATE ); //stay here if error
|
||||
break;//( USB_STATE_ERROR )
|
||||
default:
|
||||
//Should never get here
|
||||
break;
|
||||
}//switch( usb_task_state & STATE_MASK )
|
||||
}
|
||||
|
||||
//place-holders for MSD (mass-storage device) drivers, we don't have them ported.
|
||||
//returns TRUE if device is successfully identified and configured, otherwise returns FALSE
|
||||
BOOL MSDProbe( BYTE addr, DWORD flags )
|
||||
{
|
||||
(void) addr;
|
||||
(void) flags;
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
BOOL MSDEventHandler( BYTE address, BYTE event, void *data, DWORD size )
|
||||
{
|
||||
(void) address;
|
||||
(void) event;
|
||||
(void) data;
|
||||
(void) size;
|
||||
return( FALSE );
|
||||
|
||||
}
|
||||
//CDC (communication device class also not supported)
|
||||
BOOL CDCProbe( BYTE address, DWORD flags )
|
||||
{
|
||||
(void) address;
|
||||
(void) flags;
|
||||
|
||||
return( FALSE );
|
||||
|
||||
}
|
||||
|
||||
BOOL CDCEventHandler( BYTE address, BYTE event, void *data, DWORD size )
|
||||
{
|
||||
(void) address;
|
||||
(void) event;
|
||||
(void) data;
|
||||
(void) size;
|
||||
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
BOOL DummyProbe( BYTE address , DWORD flags )
|
||||
{
|
||||
(void) address;
|
||||
(void) flags;
|
||||
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
BOOL DummyEventHandler( BYTE address, BYTE event, void *data, DWORD size )
|
||||
{
|
||||
(void) address;
|
||||
(void) event;
|
||||
(void) data;
|
||||
(void) size;
|
||||
|
||||
return( FALSE );
|
||||
}
|
||||
/* Function to access usb_task_state variable from outside */
|
||||
BYTE GetUsbTaskState( void )
|
||||
{
|
||||
return( usb_task_state );
|
||||
}
|
||||
/* Function to access devtable[] from outside */
|
||||
DEV_RECORD* GetDevtable( BYTE index )
|
||||
{
|
||||
return( &devtable[ index ] );
|
||||
}
|
||||
|
||||
char* ConvUTF8ToStr(BYTE* utf8, BYTE length)
|
||||
{
|
||||
BYTE i;
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
utf8[i] = utf8[2*i];
|
||||
}
|
||||
utf8[length] = 0x00;
|
||||
return (char*)utf8;
|
||||
}
|
||||
@@ -1,253 +0,0 @@
|
||||
/* USB transfers support header */
|
||||
|
||||
#ifndef _transfer_h_
|
||||
#define _transfer_h_
|
||||
|
||||
/* Targeted peripheral list table */
|
||||
#define USB_NUMTARGETS 4 //number of targets in TPL, not counting uninitialized device
|
||||
#define USB_NUMDEVICES 8 //number of supported devices
|
||||
#define USB_NUMCLASSES 5 //number of device classes in class callback table
|
||||
#define UNINIT 0 //uninitialized
|
||||
#define HID_K 1 //HID Keyboard boot driver number in DEV_RECORD
|
||||
#define HID_M 2 //HID Mouse boot driver number in DEV_RECORD
|
||||
#define MSD 3 //Mass storage class driver number in DEV_RECORD
|
||||
#define RAPHNET 4
|
||||
|
||||
/* Standard Device Requests */
|
||||
|
||||
#define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS
|
||||
#define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE
|
||||
#define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE
|
||||
#define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS
|
||||
#define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR
|
||||
#define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR
|
||||
#define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION
|
||||
#define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION
|
||||
#define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE
|
||||
#define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE
|
||||
#define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME
|
||||
|
||||
#define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt
|
||||
#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up
|
||||
#define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode
|
||||
|
||||
/* Setup Data Constants */
|
||||
|
||||
#define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer
|
||||
#define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer
|
||||
#define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard
|
||||
#define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class
|
||||
#define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor
|
||||
#define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device
|
||||
#define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface
|
||||
#define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint
|
||||
#define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other
|
||||
|
||||
/* USB descriptors */
|
||||
|
||||
#define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor.
|
||||
#define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor.
|
||||
#define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor.
|
||||
#define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor.
|
||||
#define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor.
|
||||
#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier.
|
||||
#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration.
|
||||
#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power.
|
||||
#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor.
|
||||
|
||||
/* OTG SET FEATURE Constants */
|
||||
#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP
|
||||
#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP
|
||||
#define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP
|
||||
|
||||
/* USB Endpoint Transfer Types */
|
||||
#define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint.
|
||||
#define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint.
|
||||
#define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint.
|
||||
#define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint.
|
||||
#define bmUSB_TRANSFER_TYPE 0x03 // bit mask to separate transfer type from ISO attributes
|
||||
|
||||
/* Standard Feature Selectors for CLEAR_FEATURE Requests */
|
||||
#define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient
|
||||
#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient
|
||||
#define USB_FEATURE_TEST_MODE 2 // Device recipient
|
||||
|
||||
/* MSD class requests. Not part of chapter 9 */
|
||||
#define USB_MSD_GET_MAX_LUN 0xFE // Device Request code to get the maximum LUN.
|
||||
#define USB_MSD_RESET 0xFF // Device Request code to reset the device.
|
||||
|
||||
/* HID constants. Not part of chapter 9 */
|
||||
/* Class-Specific Requests */
|
||||
#define HID_REQUEST_GET_REPORT 0x01
|
||||
#define HID_REQUEST_GET_IDLE 0x02
|
||||
#define HID_REQUEST_GET_PROTOCOL 0x03
|
||||
#define HID_REQUEST_SET_REPORT 0x09
|
||||
#define HID_REQUEST_SET_IDLE 0x0A
|
||||
#define HID_REQUEST_SET_PROTOCOL 0x0B
|
||||
|
||||
/* Class Descriptor Types */
|
||||
#define HID_DESCRIPTOR_HID 0x21
|
||||
#define HID_DESCRIPTOR_REPORT 0x22
|
||||
#define HID_DESRIPTOR_PHY 0x23
|
||||
|
||||
/* Protocol Selection */
|
||||
#define BOOT_PROTOCOL 0x00
|
||||
#define RPT_PROTOCOL 0x01
|
||||
/* HID Interface Class Code */
|
||||
#define HID_INTF 0x03
|
||||
/* HID Interface Class SubClass Codes */
|
||||
#define BOOT_INTF_SUBCLASS 0x01
|
||||
/* HID Interface Class Protocol Codes */
|
||||
#define HID_PROTOCOL_NONE 0x00
|
||||
#define HID_PROTOCOL_KEYBOARD 0x01
|
||||
#define HID_PROTOCOL_MOUSE 0x02
|
||||
|
||||
/* USB Setup Packet Structure */
|
||||
typedef struct {
|
||||
union { // offset description
|
||||
BYTE bmRequestType; // 0 Bit-map of request type
|
||||
struct {
|
||||
unsigned int recipient :5; // Recipient of the request
|
||||
unsigned int type :2; // Type of request
|
||||
unsigned int direction :1; // Direction of data X-fer
|
||||
};
|
||||
} ReqType_u;
|
||||
BYTE bRequest; // 1 Request
|
||||
union {
|
||||
WORD wValue; // 2 Depends on bRequest
|
||||
struct {
|
||||
BYTE wValueLo;
|
||||
BYTE wValueHi;
|
||||
};
|
||||
} wVal_u;
|
||||
WORD wIndex; // 4 Depends on bRequest
|
||||
WORD wLength; // 6 Depends on bRequest
|
||||
} SETUP_PKT, *PSETUP_PKT;
|
||||
|
||||
/* Endpoint information structure */
|
||||
/* bToggle of endpoint 0 initialized to 0xff */
|
||||
/* during enumeration bToggle is set to 00 */
|
||||
typedef struct {
|
||||
BYTE epAddr; //copy from endpoint descriptor. Bit 7 indicates direction ( ignored for control endpoints )
|
||||
BYTE Attr; // Endpoint transfer type.
|
||||
WORD MaxPktSize; // Maximum packet size.
|
||||
BYTE Interval; // Polling interval in frames.
|
||||
BYTE sndToggle; //last toggle value, bitmask for HCTL toggle bits
|
||||
BYTE rcvToggle; //last toggle value, bitmask for HCTL toggle bits
|
||||
/* not sure if both are necessary */
|
||||
} EP_RECORD;
|
||||
/* device record structure */
|
||||
typedef struct {
|
||||
EP_RECORD* epinfo; //device endpoint information
|
||||
BYTE devclass; //device class
|
||||
} DEV_RECORD;
|
||||
|
||||
//targeted peripheral list element
|
||||
//NOTE: this is currently not implemented - typically an embedded host will provide a TPL
|
||||
//to enumerate supported devices.
|
||||
typedef struct {
|
||||
union {
|
||||
DWORD val;
|
||||
struct {
|
||||
WORD idVendor;
|
||||
WORD idProduct;
|
||||
};
|
||||
struct {
|
||||
BYTE bClass;
|
||||
BYTE bSubClass;
|
||||
BYTE bProtocol;
|
||||
};
|
||||
} dev_u;
|
||||
BYTE bConfig; //configuration
|
||||
BYTE numep; //number of endpoints
|
||||
EP_RECORD* epinfo; //endpoint information structure
|
||||
BYTE CltDrv; //client driver
|
||||
const char * desc; //device description
|
||||
} USB_TPL_ENTRY;
|
||||
/* control transfer */
|
||||
typedef BYTE (*CTRL_XFER)(BYTE addr, BYTE ep, WORD nbytes, BYTE* dataptr,
|
||||
BOOL direction);
|
||||
/* class driver initialization */
|
||||
typedef BOOL (*CLASS_INIT)(BYTE address, DWORD flags);
|
||||
/* class driver event handler */
|
||||
typedef BOOL (*CLASS_EVENT_HANDLER)(BYTE address, BYTE event, void *data,
|
||||
DWORD size);
|
||||
/* Client Driver Table Structure */
|
||||
typedef struct {
|
||||
CLASS_INIT Initialize; // Initialization routine
|
||||
CLASS_EVENT_HANDLER EventHandler; // Event routine
|
||||
DWORD flags; // Initialization flags
|
||||
} CLASS_CALLBACK_TABLE;
|
||||
|
||||
/* Common setup data constant combinations */
|
||||
#define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //get descriptor request type
|
||||
#define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //set request type for all but 'set feature' and 'set interface'
|
||||
#define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE //get interface request type
|
||||
|
||||
#define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
|
||||
#define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
|
||||
|
||||
/* Function macros */
|
||||
|
||||
//char XferCtrlReq( BYTE addr, BYTE ep, BYTE bmReqType, BYTE bRequest, BYTE wValLo, BYTE wValHi, WORD wInd, WORD nbytes, char* dataptr )
|
||||
/* Set address request macro. Human-readable form of bXferCtrlReq */
|
||||
/* won't necessarily work for device in 'Configured' state */
|
||||
#define XferSetAddr( oldaddr, ep, newaddr ) \
|
||||
XferCtrlReq( oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL )
|
||||
/* Set Configuration Request */
|
||||
#define XferSetConf( addr, ep, conf_value ) \
|
||||
XferCtrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL )
|
||||
///* Get configuration request */
|
||||
//#define bXferGetConf( addr, ep, urb_ptr ) bXferCtrlReq( addr, ep, 1, ( bmREQ_GET_DESCR ), USB_REQUEST_GET_CONFIGURATION, 0x00, 0x00, 0x00, urb_ptr );
|
||||
/* Get device descriptor request macro */
|
||||
#define XferGetDevDescr( addr, ep, nbytes, dataptr ) \
|
||||
XferCtrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr )
|
||||
///* Get configuration descriptor request macro */
|
||||
#define XferGetConfDescr( addr, ep, nbytes, conf, dataptr ) \
|
||||
XferCtrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr )
|
||||
///* Get string descriptor request macro */
|
||||
#define XferGetStrDescr( addr, ep, nbytes, index, langid, dataptr ) \
|
||||
XferCtrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nbytes, dataptr )
|
||||
///* Get MAX LUN MSD class request macro */
|
||||
//#define bXferGetMaxLUN( addr, intf, urb_ptr ) bXferCtrlReq( addr, 0, 1, ( bmREQ_CL_GET_INTF ), USB_MSD_GET_MAX_LUN, 0, 0, intf, urb_ptr )
|
||||
#define XferGetHIDDescr(addr, ep, desc, nbytes, dataptr) \
|
||||
XferCtrlReq(addr, ep, bmREQ_HIDIN, USB_REQUEST_GET_DESCRIPTOR, desc, HID_DESCRIPTOR_REPORT, 0x000, nbytes, dataptr)
|
||||
/* class requests */
|
||||
#define XferSetProto( addr, ep, interface, protocol ) \
|
||||
XferCtrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, NULL )
|
||||
#define XferGetProto( addr, ep, interface, dataptr ) \
|
||||
XferCtrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr )
|
||||
#define XferGetIdle( addr, ep, interface, reportID, dataptr ) \
|
||||
XferCtrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, interface, 0x0001, dataptr )
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
BYTE XferCtrlReq(BYTE addr, BYTE ep, BYTE bmReqType, BYTE bRequest, BYTE wValLo,
|
||||
BYTE wValHi, WORD wInd, WORD nbytes, BYTE* dataptr);
|
||||
BYTE XferCtrlData(BYTE addr, BYTE ep, WORD nbytes, BYTE* dataptr,
|
||||
BOOL direction);
|
||||
BYTE XferCtrlND(BYTE addr, BYTE ep, WORD nbytes, BYTE* dataptr, BOOL direction);
|
||||
//BYTE startCtrlReq( BYTE addr, BYTE ep, BYTE bmReqType, BYTE bRequest, BYTE wValLo, BYTE wValHi, WORD wInd, WORD nbytes, char* dataptr );
|
||||
BYTE XferDispatchPkt(BYTE token, BYTE ep);
|
||||
BYTE XferInTransfer(BYTE addr, BYTE ep, WORD nbytes, BYTE* data,
|
||||
BYTE maxpktsize);
|
||||
//BYTE XferInTransfer_mps( BYTE ep, char* data, BYTE maxpktsize );
|
||||
void USB_init(void);
|
||||
void USB_Task(void);
|
||||
BYTE GetUsbTaskState(void);
|
||||
DEV_RECORD* GetDevtable(BYTE index);
|
||||
|
||||
/* Client driver routines */
|
||||
BOOL MSDProbe(BYTE address, DWORD flags);
|
||||
BOOL MSDEventHandler(BYTE address, BYTE event, void *data, DWORD size);
|
||||
BOOL CDCProbe(BYTE address, DWORD flags);
|
||||
BOOL CDCEventHandler(BYTE address, BYTE event, void *data, DWORD size);
|
||||
BOOL RaphnetProbe(BYTE address, DWORD flags);
|
||||
BOOL RaphnetEventHandler(BYTE address, BYTE event, void *data, DWORD size);
|
||||
BOOL DummyProbe(BYTE address, DWORD flags);
|
||||
BOOL DummyEventHandler(BYTE address, BYTE event, void *data, DWORD size);
|
||||
|
||||
//Function to be able to display string descriptors
|
||||
char* ConvUTF8ToStr(BYTE* utf8, BYTE length);
|
||||
|
||||
#endif //_transfer_h_
|
||||
189
sw/usb/usb_ch9.h
189
sw/usb/usb_ch9.h
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
|
||||
USB Chapter 9 Protocol (Header File)
|
||||
|
||||
This file defines data structures, constants, and macros that are used to
|
||||
to support the USB Device Framework protocol described in Chapter 9 of the
|
||||
USB 2.0 specification.
|
||||
|
||||
In addition to that, class-specific descriptors are typedef'd here as well to keep descriptors together.
|
||||
They are typedefs anyway and won't take any real code space.
|
||||
*/
|
||||
|
||||
#ifndef _USB_CH9_H_
|
||||
#define _USB_CH9_H_
|
||||
|
||||
/* Misc.USB constants */
|
||||
#define DEV_DESCR_LEN 18 //device descriptor length
|
||||
#define CONF_DESCR_LEN 9 //configuration descriptor length
|
||||
#define INTR_DESCR_LEN 9 //interface descriptor length
|
||||
#define EP_DESCR_LEN 7 //endpoint descriptor length
|
||||
/* Device descriptor structure */
|
||||
typedef struct {
|
||||
BYTE bLength; // Length of this descriptor.
|
||||
BYTE bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE).
|
||||
WORD bcdUSB; // USB Spec Release Number (BCD).
|
||||
BYTE bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
BYTE bDeviceSubClass; // Subclass code (assigned by the USB-IF).
|
||||
BYTE bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
BYTE bMaxPacketSize0; // Maximum packet size for endpoint 0.
|
||||
WORD idVendor; // Vendor ID (assigned by the USB-IF).
|
||||
WORD idProduct; // Product ID (assigned by the manufacturer).
|
||||
WORD bcdDevice; // Device release number (BCD).
|
||||
BYTE iManufacturer; // Index of String Descriptor describing the manufacturer.
|
||||
BYTE iProduct; // Index of String Descriptor describing the product.
|
||||
BYTE iSerialNumber; // Index of String Descriptor with the device's serial number.
|
||||
BYTE bNumConfigurations; // Number of possible configurations.
|
||||
} USB_DEVICE_DESCRIPTOR;
|
||||
/* Configuration Descriptor Structure */
|
||||
typedef struct {
|
||||
BYTE bLength; // Length of this descriptor.
|
||||
BYTE bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION).
|
||||
WORD wTotalLength; // Total length of all descriptors for this configuration.
|
||||
BYTE bNumInterfaces; // Number of interfaces in this configuration.
|
||||
BYTE bConfigurationValue; // Value of this configuration (1 based).
|
||||
BYTE iConfiguration; // Index of String Descriptor describing the configuration.
|
||||
BYTE bmAttributes; // Configuration characteristics.
|
||||
BYTE bMaxPower; // Maximum power consumed by this configuration.
|
||||
} USB_CONFIGURATION_DESCRIPTOR;
|
||||
/* Conf.descriptor attribute bits */
|
||||
#define USB_CFG_DSC_REQUIRED 0x80 // Required attribute
|
||||
//#define USB_CFG_DSC_SELF_PWR (0x40|USB_CFG_DSC_REQUIRED) // Device is self powered.
|
||||
//#define USB_CFG_DSC_REM_WAKE (0x20|USB_CFG_DSC_REQUIRED) // Device can request remote wakup
|
||||
#define USB_CFG_DSC_SELF_PWR (0x40) // Device is self powered.
|
||||
#define USB_CFG_DSC_REM_WAKE (0x20) // Device can request remote wakup
|
||||
/* USB Interface Descriptor Structure */
|
||||
typedef struct {
|
||||
BYTE bLength; // Length of this descriptor.
|
||||
BYTE bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE).
|
||||
BYTE bInterfaceNumber; // Number of this interface (0 based).
|
||||
BYTE bAlternateSetting; // Value of this alternate interface setting.
|
||||
BYTE bNumEndpoints; // Number of endpoints in this interface.
|
||||
BYTE bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
BYTE bInterfaceSubClass; // Subclass code (assigned by the USB-IF).
|
||||
BYTE bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
BYTE iInterface; // Index of String Descriptor describing the interface.
|
||||
} USB_INTERFACE_DESCRIPTOR;
|
||||
/* USB Endpoint Descriptor Structure */
|
||||
typedef struct {
|
||||
BYTE bLength; // Length of this descriptor.
|
||||
BYTE bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT).
|
||||
BYTE bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN).
|
||||
BYTE bmAttributes; // Endpoint transfer type.
|
||||
WORD wMaxPacketSize; // Maximum packet size.
|
||||
BYTE bInterval; // Polling interval in frames.
|
||||
} USB_ENDPOINT_DESCRIPTOR;
|
||||
/* Endpoint Direction */
|
||||
#define EP_DIR_IN 0x80 // Data flows from device to host
|
||||
#define EP_DIR_OUT 0x00 // Data flows from host to device
|
||||
/* USB Endpoint Attributes */
|
||||
// Section: Transfer Types
|
||||
#define EP_ATTR_CONTROL (0<<0) // Endoint used for control transfers
|
||||
#define EP_ATTR_ISOCH (1<<0) // Endpoint used for isochronous transfers
|
||||
#define EP_ATTR_BULK (2<<0) // Endpoint used for bulk transfers
|
||||
#define EP_ATTR_INTR (3<<0) // Endpoint used for interrupt transfers
|
||||
// Section: Synchronization Types (for isochronous enpoints)
|
||||
#define EP_ATTR_NO_SYNC (0<<2) // No Synchronization
|
||||
#define EP_ATTR_ASYNC (1<<2) // Asynchronous
|
||||
#define EP_ATTR_ADAPT (2<<2) // Adaptive synchronization
|
||||
#define EP_ATTR_SYNC (3<<2) // Synchronous
|
||||
// Section: Usage Types (for isochronous endpoints)
|
||||
#define EP_ATTR_DATA (0<<4) // Data Endpoint
|
||||
#define EP_ATTR_FEEDBACK (1<<4) // Feedback endpoint
|
||||
#define EP_ATTR_IMP_FB (2<<4) // Implicit Feedback data EP
|
||||
// Section: Max Packet Sizes
|
||||
#define EP_MAX_PKT_INTR_LS 8 // Max low-speed interrupt packet
|
||||
#define EP_MAX_PKT_INTR_FS 64 // Max full-speed interrupt packet
|
||||
#define EP_MAX_PKT_ISOCH_FS 1023 // Max full-speed isochronous packet
|
||||
#define EP_MAX_PKT_BULK_FS 64 // Max full-speed bulk packet
|
||||
#define EP_LG_PKT_BULK_FS 32 // Large full-speed bulk packet
|
||||
#define EP_MED_PKT_BULK_FS 16 // Medium full-speed bulk packet
|
||||
#define EP_SM_PKT_BULK_FS 8 // Small full-speed bulk packet
|
||||
/* USB OTG Descriptor Structure */
|
||||
typedef struct {
|
||||
BYTE bLength; // Length of this descriptor.
|
||||
BYTE bDescriptorType; // OTG descriptor type (USB_DESCRIPTOR_OTG).
|
||||
BYTE bmAttributes; // OTG attributes.
|
||||
} USB_OTG_DESCRIPTOR;
|
||||
/* USB String Descriptor Structure */
|
||||
typedef struct {
|
||||
BYTE bLength; //size of this descriptor
|
||||
BYTE bDescriptorType; //type, USB_DSC_STRING
|
||||
BYTE bString[256 - 2]; //buffer for string
|
||||
} USB_STRING_DESCRIPTOR;
|
||||
/* Section: USB Device Qualifier Descriptor Structure */
|
||||
typedef struct {
|
||||
BYTE bLength; // Size of this descriptor
|
||||
BYTE bDescriptorType; // Type, always USB_DESCRIPTOR_DEVICE_QUALIFIER
|
||||
WORD bcdUSB; // USB spec version, in BCD
|
||||
BYTE bDeviceClass; // Device class code
|
||||
BYTE bDeviceSubClass; // Device sub-class code
|
||||
BYTE bDeviceProtocol; // Device protocol
|
||||
BYTE bMaxPacketSize0; // EP0, max packet size
|
||||
BYTE bNumConfigurations; // Number of "other-speed" configurations
|
||||
BYTE bReserved; // Always zero (0)
|
||||
} USB_DEVICE_QUALIFIER_DESCRIPTOR;
|
||||
/* Section: USB Specification Constants */
|
||||
#define PID_OUT 0x1 // PID for an OUT token
|
||||
#define PID_ACK 0x2 // PID for an ACK handshake
|
||||
#define PID_DATA0 0x3 // PID for DATA0 data
|
||||
#define PID_PING 0x4 // Special PID PING
|
||||
#define PID_SOF 0x5 // PID for a SOF token
|
||||
#define PID_NYET 0x6 // PID for a NYET handshake
|
||||
#define PID_DATA2 0x7 // PID for DATA2 data
|
||||
#define PID_SPLIT 0x8 // Special PID SPLIT
|
||||
#define PID_IN 0x9 // PID for a IN token
|
||||
#define PID_NAK 0xA // PID for a NAK handshake
|
||||
#define PID_DATA1 0xB // PID for DATA1 data
|
||||
#define PID_PRE 0xC // Special PID PRE (Same as PID_ERR)
|
||||
#define PID_ERR 0xC // Special PID ERR (Same as PID_PRE)
|
||||
#define PID_SETUP 0xD // PID for a SETUP token
|
||||
#define PID_STALL 0xE // PID for a STALL handshake
|
||||
#define PID_MDATA 0xF // PID for MDATA data
|
||||
|
||||
#define PID_MASK_DATA 0x03 // Data PID mask
|
||||
#define PID_MASK_DATA_SHIFTED (PID_MASK_DATA << 2) // Data PID shift to proper position
|
||||
|
||||
#define LANG_EN_US 0x0409 //US language code, probably the only supported by string descriptors
|
||||
|
||||
/* USB Token Types */
|
||||
/* defined in MAX3421E.h */
|
||||
|
||||
/* Section: OTG Descriptor Constants */
|
||||
#define OTG_HNP_SUPPORT 0x02 // OTG Descriptor bmAttributes - HNP support flag
|
||||
#define OTG_SRP_SUPPORT 0x01 // OTG Descriptor bmAttributes - SRP support flag
|
||||
/* Section: USB Class Code Definitions */
|
||||
#define USB_HUB_CLASSCODE 0x09 // Class code for a hub.
|
||||
|
||||
/* HID class-specific defines */
|
||||
|
||||
/* USB HID Descriptor header per HID 1.1 spec */
|
||||
/* section 6.2.1 */
|
||||
/* the header is variable length. Only first class descriptor fields are defined */
|
||||
typedef union {
|
||||
struct {
|
||||
BYTE bLength;
|
||||
BYTE bDescriptorType;
|
||||
WORD bcdHID;
|
||||
BYTE bCountryCode;
|
||||
BYTE bNumDescriptors;
|
||||
BYTE bDescrType;
|
||||
WORD wDescriptorLength;
|
||||
};
|
||||
} USB_HID_DESCRIPTOR;
|
||||
|
||||
/* combined descriptor for easy parsing */
|
||||
typedef struct {
|
||||
union {
|
||||
BYTE buf[80];
|
||||
USB_DEVICE_DESCRIPTOR device;
|
||||
USB_CONFIGURATION_DESCRIPTOR config;
|
||||
USB_INTERFACE_DESCRIPTOR interface;
|
||||
USB_ENDPOINT_DESCRIPTOR endpoint;
|
||||
USB_STRING_DESCRIPTOR string;
|
||||
/* class descriptors */
|
||||
USB_HID_DESCRIPTOR HID;
|
||||
} descr;
|
||||
} USB_DESCR;
|
||||
#endif // _USB_CH9_H_
|
||||
|
||||
Reference in New Issue
Block a user