1
0
mirror of https://github.com/mist-devel/mist-firmware.git synced 2026-04-17 00:15:25 +00:00

Small joystick fixes

This commit is contained in:
harbaum
2014-03-19 19:12:43 +00:00
parent bd83908bf0
commit 57d45c91de
11 changed files with 671 additions and 71 deletions

View File

@@ -9,7 +9,7 @@ TODAY = `date +"%m/%d/%y"`
PRJ = firmware
SRC = Cstartup_SAM7.c fat.c fdd.c firmware.c fpga.c hardware.c hdd.c main.c menu.c mmc.c osd.c syscalls.c user_io.c boot_print.c boot_logo.c rafile.c config.c tos.c ikbd.c
SRC += usb/max3421e.c usb/usb.c usb/hub.c usb/hid.c usb/hidparser.c usb/timer.c
SRC += usb/max3421e.c usb/usb.c usb/hub.c usb/hid.c usb/hidparser.c usb/timer.c usb/asix.c
SRC += cdc_enumerate.c cdc_control.c
OBJ = $(SRC:.c=.o)
@@ -20,7 +20,7 @@ LIBDIR =
# Commandline options for each tool.
DFLAGS = -I. -Iusb -DMIST
CFLAGS = $(DFLAGS) -c -fno-common -O3 -fsigned-char -DVDATE=\"`date +"%y%m%d"`\"
CFLAGS = $(DFLAGS) -c -fno-common -O2 -fsigned-char -DVDATE=\"`date +"%y%m%d"`\"
AFLAGS = -ahls -mapcs-32
LFLAGS = -nostartfiles -Wl,-Map,$(PRJ).map -T$(LINKMAP) $(LIBDIR)
CPFLAGS = --output-target=ihex

View File

@@ -55,4 +55,12 @@
#define bit8_debugf(...)
#endif
#if 1
// usb asix debug output in blue
#define asix_debugf(a, ...) iprintf("\033[1;34mASIX: " a "\033[0m\n", ##__VA_ARGS__)
#else
#define asix_debugf(...)
#endif
#endif // DEBUG_H

View File

@@ -152,7 +152,10 @@ void USART_Poll(void) {
}
void USART_Write(unsigned char c) {
#if 0
while(!(AT91C_BASE_US0->US_CSR & AT91C_US_TXRDY));
AT91C_BASE_US0->US_THR = c;
#else
if((AT91C_BASE_US0->US_CSR & AT91C_US_TXRDY) && (tx_wptr == tx_rptr)) {
// transmitter ready and buffer empty? -> send directly
AT91C_BASE_US0->US_THR = c;
@@ -165,6 +168,7 @@ void USART_Write(unsigned char c) {
}
AT91C_BASE_US0->US_IER = AT91C_US_TXRDY; // enable interrupt
#endif
}
void USART_Init(unsigned long baudrate) {

557
usb/asix.c Normal file
View File

@@ -0,0 +1,557 @@
//
// asix.c
//
// http://lxr.free-electrons.com/source/drivers/net/usb/asix.c?v=3.1
/*
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 3
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 255 Vendor Specific Subclass
bInterfaceProtocol 0
iInterface 7
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 11
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
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 0x03 EP 3 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
*/
#include <stdio.h>
#include "debug.h"
#include "usb.h"
#include "asix.h"
#include "timer.h"
#include "mii.h"
#include "max3421e.h"
// currently only AX88772 is supported as that's the only
// device i have
#define ASIX_TYPE_AX88772 0x01
// list of suppoerted/tested devices
static const struct {
uint16_t vid;
uint16_t pid;
uint8_t type;
} asix_devs[] = {
// DLink DUB-E100 H/W Ver B1 Alternate
{ 0x2001, 0x3c05, ASIX_TYPE_AX88772 },
{ 0, 0, 0 }
};
#define ETH_ALEN 6
/* ASIX AX8817X based USB 2.0 Ethernet Devices */
#define AX_CMD_SET_SW_MII 0x06
#define AX_CMD_READ_MII_REG 0x07
#define AX_CMD_WRITE_MII_REG 0x08
#define AX_CMD_SET_HW_MII 0x0a
#define AX_CMD_READ_EEPROM 0x0b
#define AX_CMD_WRITE_EEPROM 0x0c
#define AX_CMD_WRITE_ENABLE 0x0d
#define AX_CMD_WRITE_DISABLE 0x0e
#define AX_CMD_READ_RX_CTL 0x0f
#define AX_CMD_WRITE_RX_CTL 0x10
#define AX_CMD_READ_IPG012 0x11
#define AX_CMD_WRITE_IPG0 0x12
#define AX_CMD_WRITE_IPG1 0x13
#define AX_CMD_READ_NODE_ID 0x13
#define AX_CMD_WRITE_IPG2 0x14
#define AX_CMD_WRITE_MULTI_FILTER 0x16
#define AX88172_CMD_READ_NODE_ID 0x17
#define AX_CMD_READ_PHY_ID 0x19
#define AX_CMD_READ_MEDIUM_STATUS 0x1a
#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
#define AX_CMD_READ_MONITOR_MODE 0x1c
#define AX_CMD_WRITE_MONITOR_MODE 0x1d
#define AX_CMD_READ_GPIOS 0x1e
#define AX_CMD_WRITE_GPIOS 0x1f
#define AX_CMD_SW_RESET 0x20
#define AX_CMD_SW_PHY_STATUS 0x21
#define AX_CMD_SW_PHY_SELECT 0x22
#define AX_SWRESET_CLEAR 0x00
#define AX_SWRESET_RR 0x01
#define AX_SWRESET_RT 0x02
#define AX_SWRESET_PRTE 0x04
#define AX_SWRESET_PRL 0x08
#define AX_SWRESET_BZ 0x10
#define AX_SWRESET_IPRL 0x20
#define AX_SWRESET_IPPD 0x40
/* AX88772 & AX88178 RX_CTL values */
#define AX_RX_CTL_SO 0x0080
#define AX_RX_CTL_AP 0x0020
#define AX_RX_CTL_AM 0x0010
#define AX_RX_CTL_AB 0x0008
#define AX_RX_CTL_SEP 0x0004
#define AX_RX_CTL_AMALL 0x0002
#define AX_RX_CTL_PRO 0x0001
#define AX_RX_CTL_MFB_2048 0x0000
#define AX_RX_CTL_MFB_4096 0x0100
#define AX_RX_CTL_MFB_8192 0x0200
#define AX_RX_CTL_MFB_16384 0x0300
#define AX88772_IPG0_DEFAULT 0x15
#define AX88772_IPG1_DEFAULT 0x0c
#define AX88772_IPG2_DEFAULT 0x12
/* AX88772 & AX88178 Medium Mode Register */
#define AX_MEDIUM_PF 0x0080
#define AX_MEDIUM_JFE 0x0040
#define AX_MEDIUM_TFC 0x0020
#define AX_MEDIUM_RFC 0x0010
#define AX_MEDIUM_ENCK 0x0008
#define AX_MEDIUM_AC 0x0004
#define AX_MEDIUM_FD 0x0002
#define AX_MEDIUM_GM 0x0001
#define AX_MEDIUM_SM 0x1000
#define AX_MEDIUM_SBP 0x0800
#define AX_MEDIUM_PS 0x0200
#define AX_MEDIUM_RE 0x0100
#define AX88178_MEDIUM_DEFAULT \
(AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \
AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \
AX_MEDIUM_RE )
#define AX88772_MEDIUM_DEFAULT \
(AX_MEDIUM_FD | AX_MEDIUM_RFC | \
AX_MEDIUM_TFC | AX_MEDIUM_PS | \
AX_MEDIUM_AC | AX_MEDIUM_RE )
/* AX88772 & AX88178 RX_CTL values */
#define AX_RX_CTL_SO 0x0080
#define AX_RX_CTL_AP 0x0020
#define AX_RX_CTL_AM 0x0010
#define AX_RX_CTL_AB 0x0008
#define AX_RX_CTL_SEP 0x0004
#define AX_RX_CTL_AMALL 0x0002
#define AX_RX_CTL_PRO 0x0001
#define AX_RX_CTL_MFB_2048 0x0000
#define AX_RX_CTL_MFB_4096 0x0100
#define AX_RX_CTL_MFB_8192 0x0200
#define AX_RX_CTL_MFB_16384 0x0300
#define AX_DEFAULT_RX_CTL \
(AX_RX_CTL_SO | AX_RX_CTL_AB )
/* GPIO 0 .. 2 toggles */
#define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */
#define AX_GPIO_GPO_0 0x02 /* GPIO0 Output value */
#define AX_GPIO_GPO1EN 0x04 /* GPIO1 Output enable */
#define AX_GPIO_GPO_1 0x08 /* GPIO1 Output value */
#define AX_GPIO_GPO2EN 0x10 /* GPIO2 Output enable */
#define AX_GPIO_GPO_2 0x20 /* GPIO2 Output value */
#define AX_GPIO_RESERVED 0x40 /* Reserved */
#define AX_GPIO_RSE 0x80 /* Reload serial EEPROM */
#define ASIX_REQ_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE
#define ASIX_REQ_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE
static uint8_t asix_write_cmd(usb_device_t *dev, uint8_t cmd, uint16_t value, uint16_t index,
uint16_t size, uint8_t *data) {
asix_debugf("%s() cmd=0x%02x value=0x%04x index=0x%04x size=%d", __FUNCTION__,
cmd, value, index, size);
return(usb_ctrl_req( dev, ASIX_REQ_OUT, cmd, index, value, 0, size, data));
}
static uint8_t asix_read_cmd(usb_device_t *dev, uint8_t cmd, uint16_t value, uint16_t index,
uint16_t size, void *data) {
uint8_t buf[size];
asix_debugf("asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d",
cmd, value, index, size);
return(usb_ctrl_req( dev, ASIX_REQ_IN, cmd, index, value, 0, size, data));
}
static uint8_t asix_write_gpio(usb_device_t *dev, uint16_t value, uint16_t sleep) {
uint8_t rcode;
asix_debugf("%s() value=0x%04x sleep=%d", __FUNCTION__, value, sleep);
rcode = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL);
if(rcode) asix_debugf("Failed to write GPIO value 0x%04x: %02x\n", value, rcode);
if (sleep) timer_delay_msec(sleep);
return rcode;
}
static uint8_t asix_write_medium_mode(usb_device_t *dev, uint16_t mode) {
uint8_t rcode;
asix_debugf("asix_write_medium_mode() - mode = 0x%04x", mode);
rcode = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
if(rcode != 0)
asix_debugf("Failed to write Medium Mode mode to 0x%04x: %02x", mode, rcode);
return rcode;
}
static uint16_t asix_read_medium_status(usb_device_t *dev) {
uint16_t v;
uint8_t rcode = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS, 0, 0, 2, (uint8_t*)&v);
if (rcode != 0) {
asix_debugf("Error reading Medium Status register: %02x", rcode);
return rcode;
}
return v;
}
static inline uint8_t asix_set_sw_mii(usb_device_t *dev) {
uint8_t rcode = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
if(rcode != 0)
asix_debugf("Failed to enable software MII access");
return rcode;
}
static inline uint8_t asix_set_hw_mii(usb_device_t *dev) {
uint8_t rcode = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
if(rcode != 0)
asix_debugf("Failed to enable hardware MII access");
return rcode;
}
static inline int8_t asix_get_phy_addr(usb_device_t *dev) {
union {
uint8_t b[2];
uint16_t w;
} buf;
uint8_t ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, sizeof(buf), &buf);
asix_debugf("%s()", __FUNCTION__);
if (ret != 0) {
asix_debugf("Error reading PHYID register: %02x", ret);
return ret;
}
asix_debugf("returning 0x%04x", buf.w);
return buf.b[1];
}
static uint16_t asix_mdio_read(usb_device_t *dev, uint8_t phy_id, uint8_t loc) {
uint16_t res;
asix_set_sw_mii(dev);
asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, loc, 2, &res);
asix_set_hw_mii(dev);
asix_debugf("asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x", phy_id, loc, res);
return res;
}
static void asix_mdio_write(usb_device_t *dev, uint8_t phy_id, uint8_t loc, uint16_t val) {
asix_debugf("asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x", phy_id, loc, val);
asix_set_sw_mii(dev);
asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, loc, 2, (uint8_t*)&val);
asix_set_hw_mii(dev);
}
/* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
static uint32_t asix_get_phyid(usb_device_t *dev) {
usb_asix_info_t *info = &(dev->asix_info);
int16_t phy_reg;
uint32_t phy_id;
phy_reg = asix_mdio_read(dev, info->phy_id, MII_PHYSID1);
if(phy_reg < 0) return 0;
phy_id = (phy_reg & 0xffff) << 16;
phy_reg = asix_mdio_read(dev, info->phy_id, MII_PHYSID2);
if(phy_reg < 0) return 0;
phy_id |= (phy_reg & 0xffff);
return phy_id;
}
static uint8_t asix_sw_reset(usb_device_t *dev, uint8_t flags) {
uint8_t rcode;
rcode = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL);
if (rcode != 0)
asix_debugf("Failed to send software reset: %02x", rcode);
return rcode;
}
static uint16_t asix_read_rx_ctl(usb_device_t *dev) {
// this only works on little endian which the arm is
uint16_t v;
uint8_t rcode = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, &v);
if(rcode != 0) {
asix_debugf("Error reading RX_CTL register: %02x", rcode);
return rcode;
}
return v;
}
static uint16_t asix_write_rx_ctl(usb_device_t *dev, uint16_t mode) {
uint8_t rcode = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
if(rcode != 0)
asix_debugf("Error writing RX_CTL register: %02x", rcode);
return rcode;
}
/**
* mii_nway_restart - restart NWay (autonegotiation) for this interface
* @mii: the MII interface
*
* Returns 0 on success, negative on error.
*/
void mii_nway_restart(usb_device_t *dev) {
usb_asix_info_t *info = &(dev->asix_info);
/* if autoneg is off, it's an error */
uint16_t bmcr = asix_mdio_read(dev, info->phy_id, MII_BMCR);
if(bmcr & BMCR_ANENABLE) {
bmcr |= BMCR_ANRESTART;
asix_mdio_write(dev, info->phy_id, MII_BMCR, bmcr);
} else
asix_debugf("%s() failed", __FUNCTION__);
}
static uint8_t usb_asix_init(usb_device_t *dev) {
usb_asix_info_t *info = &(dev->asix_info);
uint8_t i, rcode = 0;
// reset status
info->qNextPollTime = 0;
info->bPollEnable = false;
info->ep.epAddr = 1;
info->ep.maxPktSize = 8;
info->ep.epAttribs = 0;
info->ep.bmNakPower = USB_NAK_NOWAIT;
asix_debugf("%s(%d)", __FUNCTION__, dev->bAddress);
union {
usb_device_descriptor_t dev_desc;
usb_configuration_descriptor_t conf_desc;
uint8_t eaddr[ETH_ALEN];
} buf;
// read full device descriptor
rcode = usb_get_dev_descr( dev, sizeof(usb_device_descriptor_t), &buf.dev_desc );
if( rcode ) {
asix_debugf("failed to get device descriptor");
return rcode;
}
// If device class is not vendor specific return
if (buf.dev_desc.bDeviceClass != USB_CLASS_VENDOR_SPECIFIC)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
asix_debugf("vid/pid = %x/%x", buf.dev_desc.idVendor, buf.dev_desc.idProduct);
// search for vid/pid in supported device list
for(i=0;asix_devs[i].type &&
((asix_devs[i].vid != buf.dev_desc.idVendor) ||
(asix_devs[i].pid != buf.dev_desc.idProduct));i++);
if(!asix_devs[i].type) {
asix_debugf("Not a supported ASIX device");
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
}
asix_debugf("supported device");
if((rcode = asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) != 0) {
asix_debugf("setting gpio failed\n");
return rcode;
}
/* 0x10 is the phy id of the embedded 10/100 ethernet phy */
int8_t embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0);
if((rcode = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL)) != 0) {
asix_debugf("Select PHY #1 failed");
return rcode;
}
if ((rcode = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL)) != 0) {
asix_debugf("reset(AX_SWRESET_IPPD | AX_SWRESET_PRL) failed");
return rcode;
}
timer_delay_msec(150);
if ((rcode = asix_sw_reset(dev, AX_SWRESET_CLEAR)) != 0) {
asix_debugf("reset(AX_SWRESET_CLEAR) failed");
return rcode;
}
timer_delay_msec(150);
if (embd_phy) {
if ((rcode = asix_sw_reset(dev, AX_SWRESET_IPRL)) != 0) {
asix_debugf("reset(AX_SWRESET_IPRL) failed");
return rcode;
}
} else {
if ((rcode = asix_sw_reset(dev, AX_SWRESET_PRTE)) != 0) {
asix_debugf("reset(AX_SWRESET_PRTE) failed");
return rcode;
}
}
timer_delay_msec(150);
uint16_t rx_ctl = asix_read_rx_ctl(dev);
asix_debugf("RX_CTL is 0x%04x after software reset", rx_ctl);
if((rcode = asix_write_rx_ctl(dev, 0x0000)) != 0) {
asix_debugf("write_rx_ctl(0) failed");
return rcode;
}
rx_ctl = asix_read_rx_ctl(dev);
asix_debugf("RX_CTL is 0x%04x setting to 0x0000", rx_ctl);
/* Get the MAC address */
if ((rcode = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
0, 0, ETH_ALEN, &buf.eaddr)) != 0) {
asix_debugf("Failed to read MAC address: %d", rcode);
return rcode;
}
iprintf("ASIX: MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
buf.eaddr[0], buf.eaddr[1], buf.eaddr[2],
buf.eaddr[3], buf.eaddr[4], buf.eaddr[5]);
info->phy_id = asix_get_phy_addr(dev);
uint32_t phyid = asix_get_phyid(dev);
iprintf("ASIX: PHYID=0x%08x\n", phyid);
if ((rcode = asix_sw_reset(dev, AX_SWRESET_PRL)) != 0) {
asix_debugf("reset(AX_SWRESET_PRL) failed");
return rcode;
}
timer_delay_msec(150);
if ((rcode = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) != 0) {
asix_debugf("reset(AX_SWRESET_IPRL | AX_SWRESET_PRL) failed");
return rcode;
}
timer_delay_msec(150);
asix_mdio_write(dev, info->phy_id, MII_BMCR, BMCR_RESET);
asix_mdio_write(dev, info->phy_id, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_CSMA);
mii_nway_restart(dev);
if ((rcode = asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT)) != 0) {
asix_debugf("asix_write_medium_mode(AX88772_MEDIUM_DEFAULT) failed\n");
return rcode;
}
if ((rcode = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
AX88772_IPG2_DEFAULT, 0, NULL)) != 0) {
asix_debugf("Write IPG,IPG1,IPG2 failed: %d", rcode);
return rcode;
}
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
if ((rcode = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) != 0)
return rcode;
iprintf("status = %x (%x)\n", asix_mdio_read(dev, info->phy_id, MII_BMSR), 12);
rx_ctl = asix_read_rx_ctl(dev);
iprintf("ASIX: RX_CTL is 0x%04x after all initializations\n", rx_ctl);
rx_ctl = asix_read_medium_status(dev);
iprintf("ASIX: Medium Status is 0x%04x after all initializations\n", rx_ctl);
info->bPollEnable = true;
return 0;
}
static uint8_t usb_asix_release(usb_device_t *dev) {
asix_debugf("%s()", __FUNCTION__);
return 0;
}
static uint8_t usb_asix_poll(usb_device_t *dev) {
usb_asix_info_t *info = &(dev->asix_info);
uint8_t rcode = 0;
if (!info->bPollEnable)
return 0;
if (info->qNextPollTime <= timer_get_msec()) {
uint16_t read = 1; // info->ep.maxPktSize;
uint8_t buf[info->ep.maxPktSize];
uint8_t rcode =
usb_in_transfer(dev, &(info->ep), &read, buf);
/* d = hrJERR */
if (rcode) {
// if (rcode != hrNAK)
// iprintf("%s() error: %x\n", __FUNCTION__, rcode);
// else
// puts("nak");
} else {
iprintf("ASIX: %d bytes\n", read);
}
info->qNextPollTime = timer_get_msec() + 1000; // poll 1 times a second
}
return rcode;
}
const usb_device_class_config_t usb_asix_class = {
usb_asix_init, usb_asix_release, usb_asix_poll };

17
usb/asix.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef ASIX_H
#define ASIX_H
#include <stdbool.h>
#include <inttypes.h>
typedef struct {
ep_t ep;
uint16_t phy_id;
uint32_t qNextPollTime; // next poll time
bool bPollEnable;
} usb_asix_info_t;
// interface to usb core
extern const usb_device_class_config_t usb_asix_class;
#endif // ASIX_H

View File

@@ -56,7 +56,7 @@ static uint8_t hid_get_report_descr(usb_device_t *dev, uint8_t iface, uint16_t s
uint8_t buf[size];
usb_hid_info_t *info = &(dev->hid_info);
uint8_t rcode = usb_ctrl_req( dev, HID_REQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,
HID_DESCRIPTOR_REPORT, iface, size, size, buf, NULL);
HID_DESCRIPTOR_REPORT, iface, size, buf);
if(!rcode) {
iprintf("HID report descriptor:\n");
@@ -81,14 +81,14 @@ static uint8_t hid_set_idle(usb_device_t *dev, uint8_t iface, uint8_t reportID,
iprintf("%s(%x, if=%d id=%d, dur=%d)\n", __FUNCTION__, dev->bAddress, iface, reportID, duration);
return( usb_ctrl_req( dev, HID_REQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID,
duration, iface, 0x0000, 0x0000, NULL, NULL ));
duration, iface, 0x0000, NULL));
}
static uint8_t hid_set_protocol(usb_device_t *dev, uint8_t iface, uint8_t protocol) {
iprintf("%s(%x, if=%d proto=%d)\n", __FUNCTION__, dev->bAddress, iface, protocol);
return( usb_ctrl_req( dev, HID_REQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol,
0x00, iface, 0x0000, 0x0000, NULL, NULL ));
0x00, iface, 0x0000, NULL));
}
static uint8_t hid_set_report(usb_device_t *dev, uint8_t iface, uint8_t report_type, uint8_t report_id,
@@ -96,7 +96,7 @@ static uint8_t hid_set_report(usb_device_t *dev, uint8_t iface, uint8_t report_t
// iprintf("%s(%x, if=%d data=%x)\n", __FUNCTION__, dev->bAddress, iface, dataptr[0]);
return( usb_ctrl_req(dev, HID_REQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id,
report_type, iface, nbytes, nbytes, dataptr, NULL ));
report_type, iface, nbytes, dataptr));
}
/* todo: handle parsing in chunks */
@@ -121,7 +121,6 @@ static uint8_t usb_hid_parse_conf(usb_device_t *dev, uint8_t conf, uint16_t len)
/* scan through all descriptors */
p = &buf;
while(len > 0) {
switch(p->conf_desc.bDescriptorType) {
case USB_DESCRIPTOR_CONFIGURATION:
iprintf("conf descriptor size %d\n", p->conf_desc.bLength);
@@ -160,7 +159,6 @@ static uint8_t usb_hid_parse_conf(usb_device_t *dev, uint8_t conf, uint16_t len)
case HID_PROTOCOL_KEYBOARD:
iprintf("HID protocol is KEYBOARD\n");
info->iface_info[info->bNumIfaces].device_type = HID_DEVICE_KEYBOARD;
// hid_set_report(dev, info->iface_info[info->bNumIfaces].iface_idx, 2, 0, 1, &kbd_led_state);
break;
case HID_PROTOCOL_MOUSE:
@@ -226,8 +224,6 @@ static uint8_t usb_hid_parse_conf(usb_device_t *dev, uint8_t conf, uint16_t len)
return USB_ERROR_CONFIGURAION_SIZE_MISMATCH;
}
iprintf("done\n");
return 0;
}
@@ -372,7 +368,7 @@ static uint8_t usb_hid_poll(usb_device_t *dev) {
// iprintf("poll %d...\n", info->ep[i].epAddr);
uint16_t read = info->ep[i].maxPktSize;
uint8_t buf[32];
uint8_t buf[info->ep[i].maxPktSize];
uint8_t rcode =
usb_in_transfer(dev, &(info->ep[i]), &read, buf);

View File

@@ -153,7 +153,7 @@ bool parse_report_descriptor(uint8_t *rep, uint16_t rep_size) {
for(c=0;c<2;c++) {
if(axis[c] >= 0) {
uint16_t cnt = bit_count + report_size * axis[c];
hidp_debugf("%c-AXIS @ %d (byte %d)\n", 'X'+c,
hidp_debugf(" (%c-AXIS @ %d (byte %d))\n", 'X'+c,
cnt, cnt/8);
// only 8 bit axes at byte boundaries are supported for
@@ -194,6 +194,7 @@ bool parse_report_descriptor(uint8_t *rep, uint16_t rep_size) {
case 10:
hidp_extreme_debugf("COLLECTION(%d)\n", value);
collection_depth++;
usage_count = 0;
if(value == 1) { // app collection
hidp_extreme_debugf(" -> application\n");
@@ -335,9 +336,7 @@ bool parse_report_descriptor(uint8_t *rep, uint16_t rep_size) {
hidp_debugf(" -> Pointer\n");
} else if((value == USAGE_X || value == USAGE_Y ||
value == USAGE_Z || value == USAGE_WHEEL) &&
app_collection) {
} else if((value == USAGE_X || value == USAGE_Y) && app_collection) {
// usage(x) and usage(y) are allowed within the app collection
hidp_extreme_debugf(" -> axis usage\n");

View File

@@ -5,32 +5,31 @@
static uint8_t usb_hub_clear_hub_feature(usb_device_t *dev, uint8_t fid ) {
return( usb_ctrl_req( dev, USB_HUB_REQ_CLEAR_HUB_FEATURE,
USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, 0, NULL, NULL ));
USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, NULL));
}
// Clear Port Feature
static uint8_t usb_hub_clear_port_feature(usb_device_t *dev, uint8_t fid, uint8_t port, uint8_t sel ) {
return( usb_ctrl_req( dev , USB_HUB_REQ_CLEAR_PORT_FEATURE,
USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000|port)|(sel<<8)), 0, 0, NULL, NULL ));
USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000|port)|(sel<<8)), 0, NULL));
}
// Get Hub Descriptor
static uint8_t usb_hub_get_hub_descriptor(usb_device_t *dev, uint8_t index,
uint16_t nbytes, usb_hub_descriptor_t *dataptr ) {
return( usb_ctrl_req( dev, USB_HUB_REQ_GET_HUB_DESCRIPTOR,
USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, nbytes,
(uint8_t*)dataptr, NULL ));
USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, (uint8_t*)dataptr));
}
// Set Port Feature
static uint8_t usb_hub_set_port_feature(usb_device_t *dev, uint8_t fid, uint8_t port, uint8_t sel ) {
return( usb_ctrl_req( dev, USB_HUB_REQ_SET_PORT_FEATURE,
USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000|sel)<<8)|port), 0, 0, NULL, NULL ));
USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000|sel)<<8)|port), 0, NULL));
}
// Get Port Status
static uint8_t usb_hub_get_port_status(usb_device_t *dev, uint8_t port, uint16_t nbytes, uint8_t* dataptr ) {
return( usb_ctrl_req( dev, USB_HUB_REQ_GET_PORT_STATUS,
USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, nbytes, dataptr, NULL ));
USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, dataptr));
}
static uint8_t usb_hub_init(usb_device_t *dev) {
@@ -209,7 +208,8 @@ static uint8_t usb_hub_check_hub_status(usb_device_t *dev, uint8_t ports) {
uint8_t buf[8];
uint16_t read = 1;
// iprintf("%s(addr=%x)\n", __FUNCTION__, addr);
// iprintf("%s(addr=%x)\n", __FUNCTION__, dev->bAddress);
rcode = usb_in_transfer(dev, &(info->ep), &read, buf);
if(rcode)
return rcode;
@@ -219,13 +219,11 @@ static uint8_t usb_hub_check_hub_status(usb_device_t *dev, uint8_t ports) {
if (buf[0] & mask) {
hub_event_t evt;
evt.bmEvent = 0;
// TODO XXXX: try sizeof(evt.evtBuff)
rcode = usb_hub_get_port_status(dev, port, 4, evt.evtBuff);
rcode = usb_hub_get_port_status(dev, port, sizeof(evt.evtBuff), evt.evtBuff);
if (rcode)
continue;
rcode = usb_hub_port_status_change(dev, port, evt);
if (rcode == HUB_ERROR_PORT_HAS_BEEN_RESET)
@@ -241,7 +239,6 @@ static uint8_t usb_hub_check_hub_status(usb_device_t *dev, uint8_t ports) {
evt.bmEvent = 0;
rcode = usb_hub_get_port_status(dev, port, 4, evt.evtBuff);
if (rcode)
continue;
@@ -252,7 +249,6 @@ static uint8_t usb_hub_check_hub_status(usb_device_t *dev, uint8_t ports) {
evt.bmChange |= USB_HUB_PORT_STATUS_PORT_CONNECTION;
rcode = usb_hub_port_status_change(dev, port, evt);
if (rcode == HUB_ERROR_PORT_HAS_BEEN_RESET)
return 0;

48
usb/mii.h Normal file
View File

@@ -0,0 +1,48 @@
#ifndef MII_H
#define MII_H
/* Generic MII registers. */
#define MII_BMCR 0x00 /* Basic mode control register */
#define MII_BMSR 0x01 /* Basic mode status register */
#define MII_PHYSID1 0x02 /* PHYS ID 1 */
#define MII_PHYSID2 0x03 /* PHYS ID 2 */
#define MII_ADVERTISE 0x04 /* Advertisement control reg */
/* Basic mode control register. */
#define BMCR_RESV 0x003f /* Unused... */
#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */
#define BMCR_CTST 0x0080 /* Collision test */
#define BMCR_FULLDPLX 0x0100 /* Full duplex */
#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
#define BMCR_RESET 0x8000 /* Reset the DP83840 */
/* Advertisement control register. */
#define ADVERTISE_SLCT 0x001f /* Selector bits */
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
#define ADVERTISE_RESV 0x1000 /* Unused... */
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
ADVERTISE_CSMA)
#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
ADVERTISE_100HALF | ADVERTISE_100FULL)
#endif // MII_H

View File

@@ -278,8 +278,7 @@ uint8_t usb_OutTransfer(ep_t *pep, uint16_t nak_limit,
uint8_t usb_ctrl_req(usb_device_t *dev, uint8_t bmReqType,
uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
uint16_t wInd, uint16_t total, uint16_t nbytes,
uint8_t* dataptr, usb_parser_t *p) {
uint16_t wInd, uint16_t nbytes, uint8_t* dataptr) {
iprintf("%s(addr=%x, len=%d, ptr=%p)\n", __FUNCTION__,
dev->bAddress, nbytes, dataptr);
bool direction = false; //request direction, IN or OUT
@@ -299,7 +298,7 @@ uint8_t usb_ctrl_req(usb_device_t *dev, uint8_t bmReqType,
setup_pkt.wVal_u.wValueLo = wValLo;
setup_pkt.wVal_u.wValueHi = wValHi;
setup_pkt.wIndex = wInd;
setup_pkt.wLength = total;
setup_pkt.wLength = nbytes;
// transfer to setup packet FIFO
max3421e_write(MAX3421E_SUDFIFO, sizeof(setup_pkt_t), (uint8_t*)&setup_pkt );
@@ -311,39 +310,15 @@ uint8_t usb_ctrl_req(usb_device_t *dev, uint8_t bmReqType,
// data stage, if present
if( dataptr != NULL ) {
if( direction ) { //IN transfer
uint16_t left = total;
dev->ep0.bmRcvToggle = 1; //bmRCVTOG1;
while (left) {
// Bytes read into buffer
uint16_t read = nbytes;
//uint16_t read = (left<nbytes) ? left : nbytes;
rcode = usb_InTransfer( &(dev->ep0), nak_limit, &read, dataptr );
if (rcode)
return rcode;
// Invoke callback function if inTransfer completed
// successfuly and callback function pointer is specified
if (!rcode && p)
(*p)(read, dataptr, total - left);
left -= read;
if (read < nbytes)
break;
}
} else {
//OUT transfer
dev->ep0.bmRcvToggle = 1;
rcode = usb_InTransfer( &(dev->ep0), nak_limit, &nbytes, dataptr );
} else { //OUT transfer
dev->ep0.bmSndToggle = 1;
rcode = usb_OutTransfer( &(dev->ep0), nak_limit, nbytes, dataptr );
}
//return error
if( rcode )
return( rcode );
if( rcode ) return( rcode );
}
// Status stage
@@ -355,6 +330,7 @@ uint8_t usb_ctrl_req(usb_device_t *dev, uint8_t bmReqType,
static const usb_device_class_config_t *class_list[] = {
&usb_hub_class,
&usb_hid_class,
&usb_asix_class,
NULL
};
@@ -465,7 +441,7 @@ void usb_poll() {
// poll all configured devices
uint8_t i;
for (i=0; i<USB_NUMDEVICES; i++)
if(dev[i].bAddress)
if(dev[i].bAddress && dev[i].class)
rcode = dev[i].class->poll(dev+i);
switch( usb_task_state ) {
@@ -474,7 +450,7 @@ void usb_poll() {
// just remove everything ...
for (i=0; i<USB_NUMDEVICES; i++) {
if (dev[i].bAddress) {
if(dev[i].bAddress && dev[i].class) {
rcode = dev[i].class->release(dev+i);
dev[i].bAddress = 0;
}
@@ -556,21 +532,21 @@ uint8_t usb_release_device(uint8_t parent, uint8_t port) {
uint8_t usb_get_dev_descr( usb_device_t *dev, uint16_t nbytes, usb_device_descriptor_t* p ) {
return( usb_ctrl_req( dev, USB_REQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR,
0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, (uint8_t*)p, NULL ));
0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, (uint8_t*)p));
}
//get configuration descriptor
uint8_t usb_get_conf_descr( usb_device_t *dev, uint16_t nbytes,
uint8_t conf, usb_configuration_descriptor_t* p ) {
return( usb_ctrl_req( dev, USB_REQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR,
conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, (uint8_t*)p, NULL ));
conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, (uint8_t*)p));
}
uint8_t usb_set_addr( usb_device_t *dev, uint8_t newaddr ) {
iprintf("%s(new=%x)\n", __FUNCTION__, newaddr);
uint8_t rcode = usb_ctrl_req( dev, USB_REQ_SET, USB_REQUEST_SET_ADDRESS, newaddr,
0x00, 0x0000, 0x0000, 0x0000, NULL, NULL );
0x00, 0x0000, 0x0000, NULL);
if(!rcode) dev->bAddress = newaddr;
return rcode;
}
@@ -578,7 +554,7 @@ uint8_t usb_set_addr( usb_device_t *dev, uint8_t newaddr ) {
//set configuration
uint8_t usb_set_conf( usb_device_t *dev, uint8_t conf_value ) {
return( usb_ctrl_req( dev, USB_REQ_SET, USB_REQUEST_SET_CONFIGURATION,
conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL ));
conf_value, 0x00, 0x0000, 0x0000, NULL));
}
void usb_SetHubPreMask() {

View File

@@ -95,6 +95,7 @@ typedef struct {
#include "hub.h"
#include "hid.h"
#include "asix.h"
// entry used for list of connected devices
typedef struct usb_device_entry {
@@ -108,6 +109,7 @@ typedef struct usb_device_entry {
union {
usb_hub_info_t hub_info;
usb_hid_info_t hid_info;
usb_asix_info_t asix_info;
};
} usb_device_t;
@@ -228,8 +230,6 @@ typedef struct {
#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration.
#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power.
typedef void(*usb_parser_t)(const uint16_t, const uint8_t *, const uint16_t);
void usb_init();
void usb_poll();
void usb_SetHubPreMask(void);
@@ -238,8 +238,7 @@ void usb_ResetHubPreMask(void);
uint8_t usb_set_addr( usb_device_t *, uint8_t );
uint8_t usb_ctrl_req( usb_device_t *, uint8_t bmReqType,
uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
uint16_t wInd, uint16_t total, uint16_t nbytes,
uint8_t* dataptr, usb_parser_t *p);
uint16_t wInd, uint16_t nbytes, uint8_t* dataptr);
uint8_t usb_get_dev_descr( usb_device_t *, uint16_t nbytes, usb_device_descriptor_t* dataptr );
uint8_t usb_get_conf_descr( usb_device_t *, uint16_t nbytes, uint8_t conf, usb_configuration_descriptor_t* dataptr );
uint8_t usb_set_conf( usb_device_t *dev, uint8_t conf_value );