static stm32_usb_ep_t ep_cnfg[ENP_MAX_NUMB];
/* USB EP0 control descriptor */
-static const usb_endpoint_descriptor_t USB_CtrlEpDescr0 =
+static const UsbEndpointDesc USB_CtrlEpDescr0 =
{
.bLength = sizeof(USB_CtrlEpDescr0),
.bDescriptorType = USB_DT_ENDPOINT,
};
/* USB EP1 control descriptor */
-static const usb_endpoint_descriptor_t USB_CtrlEpDescr1 =
+static const UsbEndpointDesc USB_CtrlEpDescr1 =
{
.bLength = sizeof(USB_CtrlEpDescr1),
.bDescriptorType = USB_DT_ENDPOINT,
};
/* USB setup packet */
-static usb_ctrlrequest_t setup_packet;
+static UsbCtrlRequest setup_packet;
/* USB device controller: max supported interfaces */
#define USB_MAX_INTERFACE 1
{
uint8_t state;
uint32_t cfg_id;
- const usb_config_descriptor_t *cfg;
+ const UsbConfigDesc *cfg;
uint32_t interfaces;
uint32_t alt[USB_MAX_INTERFACE];
uint32_t address;
static stm32_udc_t udc;
/* Generic USB Device Controller structure */
-static struct usb_device *usb_dev;
+static UsbDevice *usb_dev;
/* USB packet memory management: list of allocated chunks */
static pack_mem_slot_t *pPacketMemUse;
bool CurrentBuffer;
stm32_usb_ep_t *epd = &ep_cnfg[EP];
- ASSERT(epd->hw);
+ if (UNLIKELY(epd->hw == NULL))
+ {
+ LOG_ERR("%s: invalid endpoint (EP%d-%s)\n",
+ __func__,
+ EP >> 1,
+ (EP & 0x01) ? "IN" : "OUT");
+ ASSERT(0);
+ return;
+ }
if (epd->status != BEGIN_SERVICED && epd->status != NO_SERVICED)
return;
}
}
+/*
+ * Return the lower value from Host expected size and size and set a flag
+ * STM32_USB_EP_ZERO_POSSIBLE when size is lower that host expected size.
+ */
+static size_t usb_size(size_t size, size_t host_size)
+{
+ if (size < host_size)
+ {
+ ep_cnfg[CTRL_ENP_IN].flags |= STM32_USB_EP_ZERO_POSSIBLE;
+ return size;
+ }
+ return host_size;
+}
+
/* Configure an EP descriptor before performing a I/O operation */
#define USB_EP_IO(__EP, __op, __buf, __size, __complete) \
({ \
cpu_flags_t flags; \
stm32_usb_io_status_t ret; \
\
- /* NOTE: buffer must be 4-bytes aligned */ \
- ASSERT(!((size_t)__buf & 0x03)); \
- \
/* Fill EP descriptor */ \
IRQ_SAVE_DISABLE(flags); \
if (__size < 0) \
return USB_EP_IO(ep, write, buffer, size, complete);
}
-static bool rx_done;
-static size_t rx_size;
-
-static void usb_ep_read_complete(int ep)
-{
- if (UNLIKELY(ep >= ENP_MAX_NUMB))
- {
- ASSERT(0);
- return;
- }
- ASSERT(!(ep & 0x01));
-
- rx_done = true;
- rx_size = ep_cnfg[ep].size;
-}
-
-ssize_t usb_ep_read(int ep, void *buffer, ssize_t size)
-{
- if (UNLIKELY(!size))
- return 0;
- size = MIN(size, USB_RX_MAX_SIZE);
- rx_done = false;
- rx_size = 0;
-
- /* Blocking read */
- __usb_ep_read(USB_EpLogToPhysAdd(ep), buffer, size,
- usb_ep_read_complete);
- while (!rx_done)
- cpu_relax();
-
- return rx_size;
-}
-
-static bool tx_done;
-static size_t tx_size;
-
-static void usb_ep_write_complete(int ep)
-{
- if (UNLIKELY(ep >= ENP_MAX_NUMB))
- {
- ASSERT(0);
- return;
- }
- ASSERT(ep & 0x01);
-
- tx_done = true;
- tx_size = ep_cnfg[ep].size;
-}
-
-ssize_t usb_ep_write(int ep, const void *buffer, ssize_t size)
-{
- if (UNLIKELY(!size))
- return 0;
- size = MIN(size, USB_TX_MAX_SIZE);
- tx_done = false;
- tx_size = 0;
-
- /* Blocking write */
- __usb_ep_write(USB_EpLogToPhysAdd(ep), buffer, size,
- usb_ep_write_complete);
- while (!tx_done)
- cpu_relax();
-
- return tx_size;
-}
-
static void usb_ep_low_level_config(int ep, uint16_t offset, uint16_t size)
{
stm32_usb_ep_t *epc = &ep_cnfg[ep];
}
/* Enable/Disable an endpoint */
-static int usb_ep_configure(const usb_endpoint_descriptor_t *epd, bool enable)
+static int usb_ep_configure(const UsbEndpointDesc *epd, bool enable)
{
int EP;
stm32_usb_ep_t *ep_hw;
ep_hw->flags = 0;
/* Set endpoint type */
- ep_hw->type = usb_endpoint_type(epd);
+ ep_hw->type = usb_endpointType(epd);
/* Init EP max packet size */
ep_hw->max_size = epd->wMaxPacketSize;
/* Set Ep Address */
EpCtrlSet_EA(hw, EP >> 1);
ep_hw->hw = hw;
+ LOG_INFO("%s: EP%d-%s configured\n",
+ __func__, EP >> 1, EP & 1 ? "IN" : "OUT");
/* Low-level endpoint configuration */
usb_ep_low_level_config(EP, Offset, MaxPacketSizeTmp);
*/
static int usb_find_interface(uint32_t num, uint32_t alt)
{
- usb_interface_descriptor_t *id;
+ const UsbInterfaceDesc *id;
int i;
for (i = 0; ; i++)
{
/* TODO: support more than one configuration per device */
- id = (usb_interface_descriptor_t *)usb_dev->config[i];
+ id = (const UsbInterfaceDesc *)usb_dev->config[i];
if (id == NULL)
break;
if (id->bDescriptorType != USB_DT_INTERFACE)
static void
usb_configure_ep_interface(unsigned int num, unsigned int alt, bool enable)
{
- usb_endpoint_descriptor_t *epd;
+ const UsbEndpointDesc *epd;
int i, start;
/*
*/
for (i = start + 1; ; i++)
{
- epd = (usb_endpoint_descriptor_t *)usb_dev->config[i];
- if ((epd == NULL) || (epd->bDescriptorType != USB_DT_ENDPOINT))
+ epd = (const UsbEndpointDesc *)usb_dev->config[i];
+ if ((epd == NULL) || (epd->bDescriptorType == USB_DT_INTERFACE))
break;
+ if (epd->bDescriptorType != USB_DT_ENDPOINT)
+ continue;
if (UNLIKELY(usb_ep_configure(epd, enable) < 0))
{
LOG_ERR("%s: out of memory, can't initialize EP\n",
}
}
+static bool rx_done;
+static size_t rx_size;
+
+static void usb_ep_read_complete(int ep)
+{
+ if (UNLIKELY(ep >= ENP_MAX_NUMB))
+ {
+ ASSERT(0);
+ return;
+ }
+ ASSERT(!(ep & 0x01));
+
+ rx_done = true;
+ rx_size = ep_cnfg[ep].size;
+}
+
+ssize_t usb_ep_read(int ep, void *buffer, ssize_t size)
+{
+ int ep_num = USB_EpLogToPhysAdd(ep);
+
+ /* Non-blocking read for EP0 */
+ if (ep_num == CTRL_ENP_OUT)
+ {
+ size = usb_size(size, usb_le16_to_cpu(setup_packet.wLength));
+ if (!size)
+ USB_StatusHandler(ep_num);
+ else
+ __usb_ep_read(ep_num, buffer, size,
+ USB_StatusHandler);
+ return size;
+ }
+ if (UNLIKELY(!size))
+ return 0;
+ size = MIN(size, USB_RX_MAX_SIZE);
+ rx_done = false;
+ rx_size = 0;
+
+ /* Blocking read */
+ __usb_ep_read(ep_num, buffer, size, usb_ep_read_complete);
+ while (!rx_done)
+ cpu_relax();
+
+ return rx_size;
+}
+
+static bool tx_done;
+static size_t tx_size;
+
+static void usb_ep_write_complete(int ep)
+{
+ if (UNLIKELY(ep >= ENP_MAX_NUMB))
+ {
+ ASSERT(0);
+ return;
+ }
+ ASSERT(ep & 0x01);
+
+ tx_done = true;
+ tx_size = ep_cnfg[ep].size;
+}
+
+ssize_t usb_ep_write(int ep, const void *buffer, ssize_t size)
+{
+ int ep_num = USB_EpLogToPhysAdd(ep);
+
+ /* Non-blocking write for EP0 */
+ if (ep_num == CTRL_ENP_IN)
+ {
+ size = usb_size(size, usb_le16_to_cpu(setup_packet.wLength));
+ if (!size)
+ USB_StatusHandler(ep_num);
+ else
+ __usb_ep_write(ep_num, buffer, size,
+ USB_StatusHandler);
+ return size;
+ }
+ if (UNLIKELY(!size))
+ return 0;
+ size = MIN(size, USB_TX_MAX_SIZE);
+ tx_done = false;
+ tx_size = 0;
+
+ /* Blocking write */
+ __usb_ep_write(ep_num, buffer, size, usb_ep_write_complete);
+ while (!tx_done)
+ cpu_relax();
+
+ return tx_size;
+}
+
/* Global variable to handle the following non-blocking I/O operations */
static uint32_t InData;
return -USB_NODEV_ERROR;
InData = ((uint32_t)udc.feature) & 0xff;
- __usb_ep_write(CTRL_ENP_IN, (uint8_t *)&InData, 2, USB_StatusHandler);
-
+ __usb_ep_write(CTRL_ENP_IN,
+ (uint8_t *)&InData, sizeof(uint16_t),
+ USB_StatusHandler);
return 0;
}
static int UsbInterfaceStatus(UNUSED_ARG(uint16_t, index))
{
InData = 0;
- __usb_ep_write(CTRL_ENP_IN, (uint8_t *)&InData, 2, USB_StatusHandler);
-
+ __usb_ep_write(CTRL_ENP_IN,
+ (uint8_t *)&InData, sizeof(uint16_t),
+ USB_StatusHandler);
return 0;
}
InData = 0;
USB_GetStallEP(USB_EpLogToPhysAdd(index), (bool *)&InData);
- __usb_ep_write(CTRL_ENP_IN, (uint8_t *)&InData, 2, USB_StatusHandler);
-
+ __usb_ep_write(CTRL_ENP_IN,
+ (uint8_t *)&InData, sizeof(uint16_t),
+ USB_StatusHandler);
return 0;
}
}
}
-/*
- * Return the lower value from Host expected size and size and set a flag
- * STM32_USB_EP_ZERO_POSSIBLE when size is lower that host expected size.
- */
-static size_t usb_size(size_t size, size_t host_size)
-{
- if (size < host_size)
- {
- ep_cnfg[CTRL_ENP_IN].flags |= STM32_USB_EP_ZERO_POSSIBLE;
- return size;
- }
- return host_size;
-}
-
static int usb_get_device_descriptor(int id)
{
if (id)
usb_dev->device->bMaxPacketSize0 = USB_EP0_MAX_SIZE;
__usb_ep_write(CTRL_ENP_IN, (const uint8_t *)usb_dev->device,
usb_size(usb_dev->device->bLength,
- setup_packet.wLength),
+ usb_le16_to_cpu(setup_packet.wLength)),
USB_StatusHandler);
return 0;
}
static int usb_get_configuration_descriptor(int id)
{
- const usb_config_descriptor_t **config =
- (const usb_config_descriptor_t **)usb_dev->config;
+ const UsbConfigDesc **config =
+ (const UsbConfigDesc **)usb_dev->config;
uint8_t *p = usb_cfg_buffer;
int i;
return -USB_BUF_OVERFLOW;
}
}
- ((usb_config_descriptor_t *)usb_cfg_buffer)->wTotalLength =
+ ((UsbConfigDesc *)usb_cfg_buffer)->wTotalLength =
usb_cpu_to_le16(p - usb_cfg_buffer);
__usb_ep_write(CTRL_ENP_IN,
usb_cfg_buffer,
usb_size(p - usb_cfg_buffer,
- setup_packet.wLength),
+ usb_le16_to_cpu(setup_packet.wLength)),
USB_StatusHandler);
return 0;
}
static int usb_get_string_descriptor(unsigned int id)
{
- usb_string_descriptor_t *lang_str;
+ const UsbStringDesc *lang_str;
unsigned int lang_id, str_id;
uint16_t w_index_lo = usb_le16_to_cpu(setup_packet.wIndex) & 0x00ff;
- uint16_t w_index_hi = (usb_le16_to_cpu(setup_packet.wIndex) & 0xff00) >> 8;
+ uint16_t w_index_hi = (usb_le16_to_cpu(setup_packet.wIndex) &
+ 0xff00) >> 8;
ASSERT(usb_dev->strings != NULL);
ASSERT(usb_dev->strings[0] != NULL);
/* Find Language index */
for (lang_id = 0; ; lang_id++)
{
- usb_string_descriptor_t *str = usb_dev->strings[lang_id];
-
+ const UsbStringDesc *str =
+ usb_dev->strings[lang_id];
if (UNLIKELY(str == NULL))
return -USB_NODEV_ERROR;
if ((str->data[0] == w_index_lo) &&
}
__usb_ep_write(CTRL_ENP_IN,
lang_str,
- usb_size(lang_str->bLength, setup_packet.wLength),
+ usb_size(lang_str->bLength,
+ usb_le16_to_cpu(setup_packet.wLength)),
USB_StatusHandler);
return 0;
}
}
}
+/* USB setup packet: class/vendor request handler */
+static void usb_event_handler(UsbDevice *dev)
+{
+ /*
+ * TODO: get the appropriate usb_dev in function of the endpoint
+ * address.
+ */
+ if (dev->event_cb)
+ dev->event_cb(&setup_packet);
+}
+
/* USB setup packet: GET_DESCRIPTOR handler */
static void UBS_GetDescriptorHandler(void)
{
if ((setup_packet.mRequestType & USB_RECIP_MASK) ==
USB_RECIP_DEVICE)
UsbGetDescriptor();
+ /* Getting descriptor for a device is a standard request */
+ else if ((setup_packet.mRequestType & USB_DIR_MASK) == USB_DIR_IN)
+ usb_event_handler(usb_dev);
else
ep_cnfg[CTRL_ENP_OUT].status = STALLED;
}
ep_cnfg[CTRL_ENP_OUT].status = STALLED;
}
-static const usb_config_descriptor_t *usb_find_configuration(int num)
+static const UsbConfigDesc *usb_find_configuration(int num)
{
- const usb_config_descriptor_t *cfg;
+ const UsbConfigDesc *cfg;
int i;
for (i = 0; ; i++)
{
- cfg = (const usb_config_descriptor_t *)usb_dev->config[i];
+ cfg = (const UsbConfigDesc *)usb_dev->config[i];
if (cfg == NULL)
break;
if (cfg->bDescriptorType != USB_DT_CONFIG)
static int UsbSetConfigurationState(uint32_t Configuration)
{
- const usb_config_descriptor_t *pCnfg;
+ const UsbConfigDesc *pCnfg;
unsigned int i;
if (Configuration)
case USB_TYPE_CLASS:
LOG_INFO("%s: bmRequestType=%02x (Class)\n",
__func__, setup_packet.mRequestType);
+ usb_event_handler(usb_dev);
break;
/* Vendor */
case USB_TYPE_VENDOR:
LOG_INFO("%s: bmRequestType=%02x (Vendor)\n",
__func__, setup_packet.mRequestType);
+ usb_event_handler(usb_dev);
break;
case USB_TYPE_RESERVED:
LOG_INFO("%s: bmRequestType=%02x (Reserved)\n",
}
}
+/* USB: low-level hardware initialization */
static void usb_hw_reset(void)
{
unsigned int i;
usb_set_address(0);
/* Enable all the device interrupts */
-#if 0
usb->CNTR = bmCTRM | bmRESETM | bmSOFM | bmERRM | bmPMAOVRM |
bmSUSPM | bmWKUPM;
-#else
- /* XXX: disable frame interrupts for now (too much noise!) */
- usb->CNTR = bmCTRM | bmRESETM | bmERRM | bmPMAOVRM | bmSUSPM | bmWKUPM;
-#endif
}
/* Handle a correct transfer under ISR */
}
if (interrupt.SOF)
{
+#if 0
+ /*
+ * XXX: disable logging of frame interrupts (too much noise!)
+ */
uint16_t frame_nr = usb->FNR & 0x0fff;
-
LOG_INFO("%s: frame %#x\n", __func__, frame_nr);
+#endif
usb->ISTR = ~bmSOFM;
}
if (interrupt.WKUP)
}
/* Register an upper layer USB device into the driver */
-int usb_device_register(struct usb_device *dev)
+int usb_device_register(UsbDevice *dev)
{
#if CONFIG_KERN
MOD_CHECK(proc);