#define AO_USB_MAX_POWER 100
#endif
-#ifndef AO_USB_INTERFACE_CLASS
-#define AO_USB_INTERFACE_CLASS 0x02
+#ifndef AO_USB_SELF_POWER
+#define AO_USB_SELF_POWER 1
+#endif
+
+#define AO_USB_DEVICE_CLASS_COMMUNICATION 0x02
+#define AO_USB_INTERFACE_CLASS_CONTROL_CDC 0x02
+#define AO_USB_INTERFACE_CLASS_DATA_CDC 0x0A
+
+#ifndef AO_USB_DEVICE_CLASS
+#define AO_USB_DEVICE_CLASS AO_USB_DEVICE_CLASS_COMMUNICATION
+#endif
+
+#ifndef AO_USB_INTERFACE_CLASS_DATA
+#define AO_USB_INTERFACE_CLASS_CONTROL AO_USB_INTERFACE_CLASS_CONTROL_CDC
+#define AO_USB_INTERFACE_CLASS_DATA AO_USB_INTERFACE_CLASS_DATA_CDC
#endif
#include "ao_usb.h"
+
+#define HEADER_LEN 9
+#define CONTROL_CLASS_LEN 35
+#define DATA_LEN (9 + 7 * AO_USB_HAS_OUT + 7 * AO_USB_HAS_IN)
+
+#define TOTAL_LENGTH (HEADER_LEN + AO_USB_HAS_INT * CONTROL_CLASS_LEN + DATA_LEN)
+#define NUM_INTERFACES (AO_USB_HAS_INT + 1)
+
/* USB descriptors in one giant block of bytes */
AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
{
0x12,
AO_USB_DESC_DEVICE,
LE_WORD(0x0110), /* bcdUSB */
- 0x02, /* bDeviceClass */
+ AO_USB_DEVICE_CLASS, /* bDeviceClass */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
AO_USB_CONTROL_SIZE, /* bMaxPacketSize */
/* Configuration descriptor */
0x09,
AO_USB_DESC_CONFIGURATION,
- LE_WORD(67), /* wTotalLength */
- 0x02, /* bNumInterfaces */
+ LE_WORD(TOTAL_LENGTH), /* wTotalLength */
+ NUM_INTERFACES, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
- 0xC0, /* bmAttributes */
+ 0x80 | (AO_USB_SELF_POWER << 6), /* bmAttributes */
AO_USB_MAX_POWER >> 1, /* bMaxPower, 2mA units */
+#if AO_USB_HAS_INT
/* Control class interface */
0x09,
AO_USB_DESC_INTERFACE,
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndPoints */
- AO_USB_INTERFACE_CLASS, /* bInterfaceClass */
+ AO_USB_INTERFACE_CLASS_CONTROL, /* bInterfaceClass */
0x02, /* bInterfaceSubClass */
0x01, /* bInterfaceProtocol, linux requires value of 1 for the cdc_acm module */
0x00, /* iInterface */
0x03, /* bmAttributes = intr */
LE_WORD(8), /* wMaxPacketSize */
0xff, /* bInterval */
+#endif
/* Data class interface descriptor */
0x09,
AO_USB_DESC_INTERFACE,
- 0x01, /* bInterfaceNumber */
- 0x00, /* bAlternateSetting */
- 0x02, /* bNumEndPoints */
- 0x0A, /* bInterfaceClass = data */
- 0x00, /* bInterfaceSubClass */
- 0x00, /* bInterfaceProtocol */
- 0x00, /* iInterface */
-
+ 0x01, /* bInterfaceNumber */
+ 0x00, /* bAlternateSetting */
+ AO_USB_HAS_OUT + AO_USB_HAS_IN, /* bNumEndPoints */
+ AO_USB_INTERFACE_CLASS_DATA, /* bInterfaceClass = data */
+ 0x00, /* bInterfaceSubClass */
+ 0x00, /* bInterfaceProtocol */
+ 0x00, /* iInterface */
+
+#if AO_USB_HAS_OUT
/* Data EP OUT */
0x07,
AO_USB_DESC_ENDPOINT,
0x02, /* bmAttributes = bulk */
LE_WORD(AO_USB_OUT_SIZE),/* wMaxPacketSize */
0x00, /* bInterval */
+#endif
+#if AO_USB_HAS_IN
/* Data EP in */
0x07,
AO_USB_DESC_ENDPOINT,
0x02, /* bmAttributes = bulk */
LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */
0x00, /* bInterval */
+#endif
/* String descriptors */
0x04,
#error "must define AO_PA11_PA12_RMP"
#endif
+#ifndef AO_POWER_MANAGEMENT
+#define AO_POWER_MANAGEMENT 0
+#endif
+
#ifndef USE_USB_STDIO
#define USE_USB_STDIO 1
#endif
{
debug ("ao_usb_set_configuration\n");
+#if AO_USB_HAS_INT
/* Set up the INT end point */
ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_int_tx_offset;
ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0;
STM_USB_EPR_EP_TYPE_INTERRUPT,
STM_USB_EPR_STAT_RX_DISABLED,
STM_USB_EPR_STAT_TX_NAK);
+#endif
+#if AO_USB_HAS_OUT
/* Set up the OUT end point */
ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_out_rx_offset;
ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) |
STM_USB_EPR_EP_TYPE_BULK,
STM_USB_EPR_STAT_RX_VALID,
STM_USB_EPR_STAT_TX_DISABLED);
+#endif
+#if AO_USB_HAS_IN
/* Set up the IN end point */
ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_in_tx_offset;
ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0;
STM_USB_EPR_EP_TYPE_BULK,
STM_USB_EPR_STAT_RX_DISABLED,
STM_USB_EPR_STAT_TX_NAK);
+#endif
ao_usb_running = 1;
#if AO_USB_DIRECTIO
static uint16_t in_count;
static uint16_t out_count;
static uint16_t reset_count;
-static uint16_t suspend_count;
/* The USB memory must be accessed in 16-bit units
*/
}
}
+#if AO_POWER_MANAGEMENT
void
ao_usb_suspend(void)
{
stm_usb.cntr &= ~(1 << STM_USB_CNTR_FSUSP);
ao_power_resume();
}
+#endif
void
stm_usb_isr(void)
debug ("\treset\n");
ao_usb_set_ep0();
}
+#if AO_POWER_MANAGEMENT
if (istr & (1 << STM_USB_ISTR_SUSP)) {
- ++suspend_count;
debug ("\tsuspend\n");
ao_usb_suspend();
}
debug ("\twakeup\n");
ao_usb_wakeup();
}
+#endif
}
/* Queue the current IN buffer for transmission */
stm_usb.cntr = ((1 << STM_USB_CNTR_CTRM) |
(0 << STM_USB_CNTR_PMAOVRM) |
(0 << STM_USB_CNTR_ERRM) |
- (1 << STM_USB_CNTR_WKUPM) |
- (1 << STM_USB_CNTR_SUSPM) |
+ (AO_POWER_MANAGEMENT << STM_USB_CNTR_WKUPM) |
+ (AO_POWER_MANAGEMENT << STM_USB_CNTR_SUSPM) |
(1 << STM_USB_CNTR_RESETM) |
(0 << STM_USB_CNTR_SOFM) |
(0 << STM_USB_CNTR_ESOFM) |
static void
ao_usb_irq(void)
{
- printf ("control: %d out: %d in: %d int: %d reset: %d suspend %d\n",
- control_count, out_count, in_count, int_count, reset_count, suspend_count);
+ printf ("control: %d out: %d in: %d int: %d reset: %d\n",
+ control_count, out_count, in_count, int_count, reset_count);
}
__code struct ao_cmds ao_usb_cmds[] = {