aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/lm3s/Makefile5
-rw-r--r--lib/lpc13xx/Makefile6
-rw-r--r--lib/stm32/Makefile6
-rw-r--r--lib/stm32/can.c10
-rw-r--r--lib/stm32/vector.c26
-rw-r--r--lib/usb/usb.c6
-rw-r--r--lib/usb/usb_f103.c21
-rw-r--r--lib/usb/usb_f107.c132
-rw-r--r--lib/usb/usb_private.h1
-rw-r--r--lib/usb/usb_standard.c11
10 files changed, 159 insertions, 65 deletions
diff --git a/lib/lm3s/Makefile b/lib/lm3s/Makefile
index 25c57ec..2bdbd72 100644
--- a/lib/lm3s/Makefile
+++ b/lib/lm3s/Makefile
@@ -25,7 +25,7 @@ CC = $(PREFIX)-gcc
AR = $(PREFIX)-ar
CFLAGS = -Os -g -Wall -Wextra -I../../include -fno-common \
-mcpu=cortex-m3 -mthumb -Wstrict-prototypes \
- -ffunction-sections -fdata-sections
+ -ffunction-sections -fdata-sections -MD
# ARFLAGS = rcsv
ARFLAGS = rcs
OBJS = gpio.o vector.o
@@ -49,8 +49,9 @@ $(LIBNAME).a: $(OBJS)
clean:
@printf " CLEAN lib/lpc13xx\n"
- $(Q)rm -f *.o
+ $(Q)rm -f *.o *.d
$(Q)rm -f $(LIBNAME).a
.PHONY: clean
+-include $(OBJS:.o=.d)
diff --git a/lib/lpc13xx/Makefile b/lib/lpc13xx/Makefile
index 37889e6..7181a08 100644
--- a/lib/lpc13xx/Makefile
+++ b/lib/lpc13xx/Makefile
@@ -25,7 +25,7 @@ CC = $(PREFIX)-gcc
AR = $(PREFIX)-ar
CFLAGS = -Os -g -Wall -Wextra -I../../include -fno-common \
-mcpu=cortex-m3 -mthumb -Wstrict-prototypes \
- -ffunction-sections -fdata-sections
+ -ffunction-sections -fdata-sections -MD
# ARFLAGS = rcsv
ARFLAGS = rcs
OBJS = gpio.o
@@ -49,8 +49,10 @@ $(LIBNAME).a: $(OBJS)
clean:
@printf " CLEAN lib/lpc13xx\n"
- $(Q)rm -f *.o
+ $(Q)rm -f *.o *.d
$(Q)rm -f $(LIBNAME).a
.PHONY: clean
+-include $(OBJS:.o=.d)
+
diff --git a/lib/stm32/Makefile b/lib/stm32/Makefile
index 6ffcc4a..095f524 100644
--- a/lib/stm32/Makefile
+++ b/lib/stm32/Makefile
@@ -25,7 +25,7 @@ CC = $(PREFIX)-gcc
AR = $(PREFIX)-ar
CFLAGS = -Os -g -Wall -Wextra -I../../include -fno-common \
-mcpu=cortex-m3 -mthumb -Wstrict-prototypes \
- -ffunction-sections -fdata-sections
+ -ffunction-sections -fdata-sections -MD
# ARFLAGS = rcsv
ARFLAGS = rcs
OBJS = vector.o rcc.o gpio.o usart.o adc.o spi.o flash.o nvic.o \
@@ -52,8 +52,10 @@ $(LIBNAME).a: $(OBJS)
clean:
@printf " CLEAN lib/stm32\n"
- $(Q)rm -f *.o
+ $(Q)rm -f *.o *.d
$(Q)rm -f $(LIBNAME).a
.PHONY: clean
+-include $(OBJS:.o=.d)
+
diff --git a/lib/stm32/can.c b/lib/stm32/can.c
index 3266133..e571f8a 100644
--- a/lib/stm32/can.c
+++ b/lib/stm32/can.c
@@ -211,6 +211,8 @@ int can_transmit(u32 canport, u32 id, bool ext, bool rtr, u8 length, u8 *data)
if (ret == -1)
return ret;
+ /* Clear stale register bits */
+ CAN_TIxR(canport, mailbox) = 0;
if (ext) {
/* Set extended ID. */
CAN_TIxR(canport, mailbox) |= id << CAN_TIxR_EXID_SHIFT;
@@ -219,15 +221,11 @@ int can_transmit(u32 canport, u32 id, bool ext, bool rtr, u8 length, u8 *data)
} else {
/* Set standard ID. */
CAN_TIxR(canport, mailbox) |= id << CAN_TIxR_STID_SHIFT;
- /* Unset extended ID indicator bit. */
- CAN_TIxR(canport, mailbox) &= ~CAN_TIxR_IDE;
}
/* Set/clear remote transmission request bit. */
if (rtr)
CAN_TIxR(canport, mailbox) |= CAN_TIxR_RTR; /* Set */
- else
- CAN_TIxR(canport, mailbox) &= ~CAN_TIxR_RTR; /* Clear */
/* Set the DLC. */
CAN_TDTxR(canport, mailbox) &= 0xFFFFFFFF0;
@@ -270,12 +268,12 @@ void can_receive(u32 canport, u8 fifo, bool release, u32 *id, bool *ext,
if (CAN_RIxR(canport, fifo_id) & CAN_RIxR_IDE) {
*ext = true;
/* Get extended CAN ID. */
- *id = ((CAN_RIxR(canport, fifo_id) & CAN_RIxR_EXID_MASK) >
+ *id = ((CAN_RIxR(canport, fifo_id) & CAN_RIxR_EXID_MASK) >>
CAN_RIxR_EXID_SHIFT);
} else {
*ext = false;
/* Get standard CAN ID. */
- *id = ((CAN_RIxR(canport, fifo_id) & CAN_RIxR_STID_MASK) >
+ *id = ((CAN_RIxR(canport, fifo_id) & CAN_RIxR_STID_MASK) >>
CAN_RIxR_STID_SHIFT);
}
diff --git a/lib/stm32/vector.c b/lib/stm32/vector.c
index 4d3d510..39bd9a1 100644
--- a/lib/stm32/vector.c
+++ b/lib/stm32/vector.c
@@ -96,6 +96,15 @@ void WEAK dma2_channel1_isr(void);
void WEAK dma2_channel2_isr(void);
void WEAK dma2_channel3_isr(void);
void WEAK dma2_channel4_5_isr(void);
+void WEAK dma2_channel5_isr(void);
+void WEAK eth_isr(void);
+void WEAK eth_wkup_isr(void);
+void WEAK can2_tx_isr(void);
+void WEAK can2_rx0_isr(void);
+void WEAK can2_rx1_isr(void);
+void WEAK can2_sce_isr(void);
+void WEAK otg_fs_isr(void);
+
__attribute__ ((section(".vectors")))
void (*const vector_table[]) (void) = {
@@ -172,6 +181,14 @@ void (*const vector_table[]) (void) = {
dma2_channel2_isr,
dma2_channel3_isr,
dma2_channel4_5_isr,
+ dma2_channel5_isr,
+ eth_isr,
+ eth_wkup_isr,
+ can2_tx_isr,
+ can2_rx0_isr,
+ can2_rx1_isr,
+ can2_sce_isr,
+ otg_fs_isr,
};
void reset_handler(void)
@@ -268,3 +285,12 @@ void null_handler(void)
#pragma weak dma2_channel2_isr = null_handler
#pragma weak dma2_channel3_isr = null_handler
#pragma weak dma2_channel4_5_isr = null_handler
+#pragma weak dma2_channel5_isr
+#pragma weak eth_isr = null_handler
+#pragma weak eth_wkup_isr = null_handler
+#pragma weak can2_tx_isr = null_handler
+#pragma weak can2_rx0_isr = null_handler
+#pragma weak can2_rx1_isr = null_handler
+#pragma weak can2_sce_isr = null_handler
+#pragma weak otg_fs_isr = null_handler
+
diff --git a/lib/usb/usb.c b/lib/usb/usb.c
index eb8e6d8..59c526d 100644
--- a/lib/usb/usb.c
+++ b/lib/usb/usb.c
@@ -127,3 +127,9 @@ u8 usbd_ep_stall_get(u8 addr)
{
return _usbd_device.driver->ep_stall_get(addr);
}
+
+void usbd_ep_nak_set(u8 addr, u8 nak)
+{
+ _usbd_device.driver->ep_nak_set(addr, nak);
+}
+
diff --git a/lib/usb/usb_f103.c b/lib/usb/usb_f103.c
index ef97670..19f645d 100644
--- a/lib/usb/usb_f103.c
+++ b/lib/usb/usb_f103.c
@@ -30,10 +30,13 @@ static void stm32f103_ep_setup(u8 addr, u8 type, u16 max_size,
static void stm32f103_endpoints_reset(void);
static void stm32f103_ep_stall_set(u8 addr, u8 stall);
static u8 stm32f103_ep_stall_get(u8 addr);
+static void stm32f103_ep_nak_set(u8 addr, u8 nak);
static u16 stm32f103_ep_write_packet(u8 addr, const void *buf, u16 len);
static u16 stm32f103_ep_read_packet(u8 addr, void *buf, u16 len);
static void stm32f103_poll(void);
+static u8 force_nak[8];
+
const struct _usbd_driver stm32f103_usb_driver = {
.init = stm32f103_usbd_init,
.set_address = stm32f103_set_address,
@@ -41,6 +44,7 @@ const struct _usbd_driver stm32f103_usb_driver = {
.ep_reset = stm32f103_endpoints_reset,
.ep_stall_set = stm32f103_ep_stall_set,
.ep_stall_get = stm32f103_ep_stall_get,
+ .ep_nak_set = stm32f103_ep_nak_set,
.ep_write_packet = stm32f103_ep_write_packet,
.ep_read_packet = stm32f103_ep_read_packet,
.poll = stm32f103_poll,
@@ -177,6 +181,20 @@ static u8 stm32f103_ep_stall_get(u8 addr)
return 0;
}
+static void stm32f103_ep_nak_set(u8 addr, u8 nak)
+{
+ /* It does not make sence to force NAK on IN endpoints */
+ if(addr & 0x80)
+ return;
+
+ force_nak[addr] = nak;
+
+ if(nak)
+ USB_SET_EP_RX_STAT(addr, USB_EP_RX_STAT_NAK);
+ else
+ USB_SET_EP_RX_STAT(addr, USB_EP_RX_STAT_VALID);
+}
+
/**
* Copy a data buffer to packet memory.
*
@@ -236,7 +254,8 @@ static u16 stm32f103_ep_read_packet(u8 addr, void *buf, u16 len)
usb_copy_from_pm(buf, USB_GET_EP_RX_BUFF(addr), len);
USB_CLR_EP_RX_CTR(addr);
- USB_SET_EP_RX_STAT(addr, USB_EP_RX_STAT_VALID);
+ if(!force_nak[addr])
+ USB_SET_EP_RX_STAT(addr, USB_EP_RX_STAT_VALID);
return len;
}
diff --git a/lib/usb/usb_f107.c b/lib/usb/usb_f107.c
index a681b60..ee83b65 100644
--- a/lib/usb/usb_f107.c
+++ b/lib/usb/usb_f107.c
@@ -25,6 +25,12 @@
#include <string.h>
+/* Receive FIFO size in 32-bit words */
+#define RX_FIFO_SIZE 128
+static uint16_t fifo_mem_top;
+
+static u8 force_nak[4];
+
static void stm32f107_usbd_init(void);
static void stm32f107_set_address(u8 addr);
static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size,
@@ -32,6 +38,7 @@ static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size,
static void stm32f107_endpoints_reset(void);
static void stm32f107_ep_stall_set(u8 addr, u8 stall);
static u8 stm32f107_ep_stall_get(u8 addr);
+static void stm32f107_ep_nak_set(u8 addr, u8 nak);
static u16 stm32f107_ep_write_packet(u8 addr, const void *buf, u16 len);
static u16 stm32f107_ep_read_packet(u8 addr, void *buf, u16 len);
static void stm32f107_poll(void);
@@ -47,6 +54,7 @@ const struct _usbd_driver stm32f107_usb_driver = {
.ep_reset = stm32f107_endpoints_reset,
.ep_stall_set = stm32f107_ep_stall_set,
.ep_stall_get = stm32f107_ep_stall_get,
+ .ep_nak_set = stm32f107_ep_nak_set,
.ep_write_packet = stm32f107_ep_write_packet,
.ep_read_packet = stm32f107_ep_read_packet,
.poll = stm32f107_poll,
@@ -55,15 +63,13 @@ const struct _usbd_driver stm32f107_usb_driver = {
/** Initialize the USB device controller hardware of the STM32. */
static void stm32f107_usbd_init(void)
{
- int i;
- /* TODO: Enable interrupts on Reset, Transfer, Suspend and Resume */
+ OTG_FS_GINTSTS = OTG_FS_GINTSTS_MMIS;
/* WARNING: Undocumented! Select internal PHY */
OTG_FS_GUSBCFG |= OTG_FS_GUSBCFG_PHYSEL;
/* Enable VBUS sensing in device mode and power down the phy */
OTG_FS_GCCFG |= OTG_FS_GCCFG_VBUSBSEN | OTG_FS_GCCFG_PWRDWN;
- for(i = 0; i < 800000; i++) __asm__("nop");
/* Wait for AHB idle */
while(!(OTG_FS_GRSTCTL & OTG_FS_GRSTCTL_AHBIDL));
@@ -71,7 +77,6 @@ static void stm32f107_usbd_init(void)
OTG_FS_GRSTCTL |= OTG_FS_GRSTCTL_CSRST;
while(OTG_FS_GRSTCTL & OTG_FS_GRSTCTL_CSRST);
- for(i = 0; i < 800000; i++) __asm__("nop");
/* Force peripheral only mode. */
OTG_FS_GUSBCFG |= OTG_FS_GUSBCFG_FDMOD;
@@ -82,28 +87,30 @@ static void stm32f107_usbd_init(void)
/* Restart the phy clock */
OTG_FS_PCGCCTL = 0;
+ OTG_FS_GRXFSIZ = RX_FIFO_SIZE;
+ fifo_mem_top = RX_FIFO_SIZE;
/* Unmask interrupts for TX and RX */
- OTG_FS_GINTMSK &= OTG_FS_GINTMSK_RXFLVLM;
+ OTG_FS_GAHBCFG |= OTG_FS_GAHBCFG_GINT;
+ OTG_FS_GINTMSK = OTG_FS_GINTMSK_ENUMDNEM |
+ OTG_FS_GINTMSK_RXFLVLM |
+ OTG_FS_GINTMSK_IEPINT |
+ OTG_FS_GINTMSK_USBSUSPM |
+ OTG_FS_GINTMSK_WUIM |
+ OTG_FS_GINTMSK_SOFM;
+ OTG_FS_DAINTMSK = 0xF;
+ OTG_FS_DIEPMSK = OTG_FS_DIEPMSK_XFRCM;
}
static void stm32f107_set_address(u8 addr)
{
- /* There is something badly wrong gere! */
-
- /* TODO: Set device address and enable. */
-
- /* This I think is correct, but doesn't work at all... */
- //OTG_FS_DCFG = (OTG_FS_DCFG & ~OTG_FS_DCFG_DAD) | (addr << 4);
-
- /* This is obviously incorrect, but sometimes works... */
- OTG_FS_DCFG |= addr << 4;
+ OTG_FS_DCFG = (OTG_FS_DCFG & ~OTG_FS_DCFG_DAD) | (addr << 4);
}
static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size,
void (*callback) (u8 ep))
{
- /* TODO: Configure endpoint address and type.
+ /* Configure endpoint address and type.
* Allocate FIFO memory for endpoint.
* Install callback funciton.
*/
@@ -130,14 +137,20 @@ static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size,
OTG_FS_DOEPTSIZ(0) = doeptsiz[0];
OTG_FS_DOEPCTL(0) |= OTG_FS_DOEPCTL0_EPENA | OTG_FS_DIEPCTL0_SNAK;
+ OTG_FS_GNPTXFSIZ = ((max_size / 4) << 16) | RX_FIFO_SIZE;
+ fifo_mem_top += max_size / 4;
+
return;
}
- /* TODO: Configuration for other endpoints */
if (dir) {
+ OTG_FS_DIEPTXF(addr) = ((max_size / 4) << 16) | fifo_mem_top;
+ fifo_mem_top += max_size / 4;
+
OTG_FS_DIEPTSIZ(addr) = (max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
OTG_FS_DIEPCTL(addr) |= OTG_FS_DIEPCTL0_EPENA |
OTG_FS_DIEPCTL0_SNAK | (type << 18) |
+ OTG_FS_DIEPCTL0_USBAEP |
(addr << 22) | max_size;
if (callback) {
@@ -152,7 +165,8 @@ static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size,
(max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
OTG_FS_DOEPTSIZ(addr) = doeptsiz[addr];
OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_EPENA |
- OTG_FS_DIEPCTL0_CNAK | (type << 18) | max_size;
+ OTG_FS_DOEPCTL0_USBAEP | OTG_FS_DIEPCTL0_CNAK |
+ (type << 18) | max_size;
if (callback) {
_usbd_device.
@@ -164,41 +178,59 @@ static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size,
static void stm32f107_endpoints_reset(void)
{
- /* TODO: Reset all endpoints. */
+ /* The core resets the endpoints automatically on reset */
+ fifo_mem_top = RX_FIFO_SIZE;
}
static void stm32f107_ep_stall_set(u8 addr, u8 stall)
{
if(addr == 0) {
if(stall)
- OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_STALL;
+ OTG_FS_DIEPCTL(addr) |= OTG_FS_DIEPCTL0_STALL;
else
- OTG_FS_DOEPCTL(addr) &= ~OTG_FS_DOEPCTL0_STALL;
+ OTG_FS_DIEPCTL(addr) &= ~OTG_FS_DIEPCTL0_STALL;
}
if(addr & 0x80) {
addr &= 0x7F;
- if(stall)
+ if(stall) {
OTG_FS_DIEPCTL(addr) |= OTG_FS_DIEPCTL0_STALL;
- else
+ } else {
OTG_FS_DIEPCTL(addr) &= ~OTG_FS_DIEPCTL0_STALL;
- /* TODO: Reset to DATA0 */
+ OTG_FS_DIEPCTL(addr) |= OTG_FS_DIEPCTLX_SD0PID;
+ }
} else {
- if(stall)
+ if(stall) {
OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_STALL;
- else
+ } else {
OTG_FS_DOEPCTL(addr) &= ~OTG_FS_DOEPCTL0_STALL;
- /* TODO: Reset to DATA0 */
+ OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTLX_SD0PID;
+ }
}
}
static u8 stm32f107_ep_stall_get(u8 addr)
{
- /* TODO: return 1 if STALL set. */
- (void)addr;
+ /* return non-zero if STALL set. */
+ if(addr & 0x80)
+ return (OTG_FS_DIEPCTL(addr&0x7f) & OTG_FS_DIEPCTL0_STALL)?1:0;
+ else
+ return (OTG_FS_DOEPCTL(addr) & OTG_FS_DOEPCTL0_STALL)?1:0;
+}
+
+static void stm32f107_ep_nak_set(u8 addr, u8 nak)
+{
+ /* It does not make sence to force NAK on IN endpoints */
+ if(addr & 0x80)
+ return;
+
+ force_nak[addr] = nak;
- return 0;
+ if(nak)
+ OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_SNAK;
+ else
+ OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_CNAK;
}
static u16 stm32f107_ep_write_packet(u8 addr, const void *buf, u16 len)
@@ -247,31 +279,33 @@ static u16 stm32f107_ep_read_packet(u8 addr, void *buf, u16 len)
}
OTG_FS_DOEPTSIZ(addr) = doeptsiz[addr];
- OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_EPENA | OTG_FS_DOEPCTL0_CNAK;
+ OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_EPENA |
+ (force_nak[addr] ? OTG_FS_DOEPCTL0_SNAK : OTG_FS_DOEPCTL0_CNAK);
return len;
}
static void stm32f107_poll(void)
{
- /* TODO: Read interrupt status register */
+ /* Read interrupt status register */
u32 intsts = OTG_FS_GINTSTS;
+ int i;
if (intsts & OTG_FS_GINTSTS_ENUMDNE) {
- /* TODO: Handle USB RESET condition */
+ /* Handle USB RESET condition */
OTG_FS_GINTSTS = OTG_FS_GINTSTS_ENUMDNE;
_usbd_reset();
return;
}
- /* TODO: Handle transfer complete condition */
/* Note: RX and TX handled differently in this device. */
if (intsts & OTG_FS_GINTSTS_RXFLVL) {
/* Receive FIFO non-empty */
u32 rxstsp = OTG_FS_GRXSTSP;
u32 pktsts = rxstsp & OTG_FS_GRXSTSP_PKTSTS_MASK;
if((pktsts != OTG_FS_GRXSTSP_PKTSTS_OUT) &&
- (pktsts != OTG_FS_GRXSTSP_PKTSTS_SETUP)) return;
+ (pktsts != OTG_FS_GRXSTSP_PKTSTS_SETUP))
+ return;
u8 ep = rxstsp & OTG_FS_GRXSTSP_EPNUM_MASK;
u8 type;
@@ -285,39 +319,33 @@ static void stm32f107_poll(void)
if (_usbd_device.user_callback_ctr[ep][type])
_usbd_device.user_callback_ctr[ep][type] (ep);
- /* TODO: clear any interrupt flag */
}
/* There is no global interrupt flag for transmit complete.
* the XFRC bit must be checked in each OTG_FS_DIEPINT(x)
*/
- /* TODO: Check on endpoint interrupt... */
- {
- int i;
- for (i = 0; i < 4; i++) { /* Iterate over endpoints */
- if(OTG_FS_DIEPINT(i) & OTG_FS_DIEPINTX_XFRC) {
- /* Transfer complete */
- if (_usbd_device.user_callback_ctr[i][USB_TRANSACTION_IN])
- _usbd_device.user_callback_ctr[i][USB_TRANSACTION_IN] (i);
- OTG_FS_DIEPINT(i) = OTG_FS_DIEPINTX_XFRC;
- }
+ for (i = 0; i < 4; i++) { /* Iterate over endpoints */
+ if(OTG_FS_DIEPINT(i) & OTG_FS_DIEPINTX_XFRC) {
+ /* Transfer complete */
+ if (_usbd_device.user_callback_ctr[i][USB_TRANSACTION_IN])
+ _usbd_device.user_callback_ctr[i][USB_TRANSACTION_IN] (i);
+ OTG_FS_DIEPINT(i) = OTG_FS_DIEPINTX_XFRC;
}
}
- /* TODO: Handle suspend condition */
- if (0) {
- /* TODO: Clear suspend interrupt flag */
+ if (intsts & OTG_FS_GINTSTS_USBSUSP) {
if (_usbd_device.user_callback_suspend)
_usbd_device.user_callback_suspend();
+ OTG_FS_GINTSTS = OTG_FS_GINTSTS_USBSUSP;
}
- /* TODO: Handle wakeup condition */
- if (0) {
- /* TODO: Clear wakeup interrupt flag */
+ if (intsts & OTG_FS_GINTSTS_WKUPINT) {
if (_usbd_device.user_callback_resume)
_usbd_device.user_callback_resume();
+ OTG_FS_GINTSTS = OTG_FS_GINTSTS_WKUPINT;
}
- /* TODO: Handle SOF condition */
+ if (intsts & OTG_FS_GINTSTS_SOF)
+ OTG_FS_GINTSTS = OTG_FS_GINTSTS_SOF;
}
diff --git a/lib/usb/usb_private.h b/lib/usb/usb_private.h
index 1bc6b3f..40d59a1 100644
--- a/lib/usb/usb_private.h
+++ b/lib/usb/usb_private.h
@@ -78,6 +78,7 @@ struct _usbd_driver {
void (*ep_setup)(u8 addr, u8 type, u16 max_size, void (*cb)(u8 ep));
void (*ep_reset)(void);
void (*ep_stall_set)(u8 addr, u8 stall);
+ void (*ep_nak_set)(u8 addr, u8 nak);
u8 (*ep_stall_get)(u8 addr);
u16 (*ep_write_packet)(u8 addr, const void *buf, u16 len);
u16 (*ep_read_packet)(u8 addr, void *buf, u16 len);
diff --git a/lib/usb/usb_standard.c b/lib/usb/usb_standard.c
index 5995387..aa92010 100644
--- a/lib/usb/usb_standard.c
+++ b/lib/usb/usb_standard.c
@@ -98,6 +98,11 @@ static int usb_standard_get_descriptor(struct usb_setup_data *req,
if (!_usbd_device.strings)
return 0; /* Device doesn't support strings. */
+ /* Check that string index is in range */
+ for(i = 0; i <= (req->wValue & 0xff); i++)
+ if(_usbd_device.strings[i] == NULL)
+ return 0;
+
sd->bLength = strlen(_usbd_device.strings[req->wValue & 0xff])
* 2 + 2;
sd->bDescriptorType = USB_DT_STRING;
@@ -131,6 +136,12 @@ static int usb_standard_set_address(struct usb_setup_data *req, u8 **buf,
_usbd_device.current_address = req->wValue;
+ /* Special workaround for STM32F10[57] that require the address
+ * to be set here. This is undocumented!
+ */
+ if(_usbd_device.driver == &stm32f107_usb_driver)
+ _usbd_device.driver->set_address(req->wValue);
+
return 1;
}