aboutsummaryrefslogtreecommitdiff
path: root/lib/usb
diff options
context:
space:
mode:
authorGareth McMullin2011-03-30 07:17:02 +1300
committerGareth McMullin2011-03-30 07:17:02 +1300
commitef0ff192f769d6e043b4fdfc89cfbade61b9db14 (patch)
tree5d190367d8cbe798026705d96ff001c50b4c2106 /lib/usb
parent692266bf6734b0361151a713c5b602696637de63 (diff)
Added usbd_ep_nak_set() to force flow control on OUT endpoints.
Diffstat (limited to 'lib/usb')
-rw-r--r--lib/usb/usb.c6
-rw-r--r--lib/usb/usb_f103.c21
-rw-r--r--lib/usb/usb_f107.c21
-rw-r--r--lib/usb/usb_private.h1
4 files changed, 47 insertions, 2 deletions
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 9a20b0b..f106a05 100644
--- a/lib/usb/usb_f107.c
+++ b/lib/usb/usb_f107.c
@@ -29,6 +29,8 @@
#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,
@@ -36,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);
@@ -51,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,
@@ -210,6 +214,20 @@ static u8 stm32f107_ep_stall_get(u8 addr)
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;
+
+ 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)
{
const u32 *buf32 = buf;
@@ -256,7 +274,8 @@ 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;
}
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);