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;
+static pack_mem_slot_t *mem_use;
/* USB packet memory management: memory buffer metadata */
#define EP_MAX_SLOTS 16
-static pack_mem_slot_t PacketMemBuff[EP_MAX_SLOTS];
+static pack_mem_slot_t memory_buffer[EP_MAX_SLOTS];
/* Allocate a free block of the packet memory */
static pack_mem_slot_t *usb_malloc(void)
{
unsigned int i;
- for (i = 0; i < countof(PacketMemBuff); i++)
- if (PacketMemBuff[i].Size == 0)
- return &PacketMemBuff[i];
+ for (i = 0; i < countof(memory_buffer); i++)
+ if (memory_buffer[i].Size == 0)
+ return &memory_buffer[i];
return NULL;
}
}
/* Allocate a free chunk of the packet memory (inside a block) */
-static bool USB_AllocateBuffer(uint16_t *pOffset, uint32_t *pPacketSize,
+static bool usb_alloc_buffer(uint16_t *pOffset, uint32_t *size,
int EndPoint)
{
- pack_mem_slot_t *pPacketMem = pPacketMemUse,
- *pPacketMemNext, *pPacketMemUseNew;
- uint32_t MaxPacketSize = *pPacketSize;
+ pack_mem_slot_t *mem = mem_use,
+ *memNext, *mem_useNew;
+ uint32_t max_size = *size;
/*
* Packet size alignment:
* - fine-granularity allocation: size alignment by 2;
* - coarse-granularity allocation: size alignment by 32.
*/
- if (MaxPacketSize < 62)
- MaxPacketSize = ALIGN_UP(MaxPacketSize, 2);
+ if (max_size < 62)
+ max_size = ALIGN_UP(max_size, 2);
else
- MaxPacketSize = ALIGN_UP(MaxPacketSize, 32);
+ max_size = ALIGN_UP(max_size, 32);
/*
* Finding free memory chunks from the allocated blocks of the USB
* packet memory.
*/
*pOffset = 0;
- while (pPacketMem != NULL)
+ while (mem != NULL)
{
/* Offset alignment by 4 */
- *pOffset = ALIGN_UP(pPacketMem->Start + pPacketMem->Size, 4);
- pPacketMemNext = pPacketMem->next;
- if ((pPacketMem->next == NULL) ||
- (pPacketMemNext->Start >=
- *pOffset + MaxPacketSize))
+ *pOffset = ALIGN_UP(mem->Start + mem->Size, 4);
+ memNext = mem->next;
+ if ((mem->next == NULL) ||
+ (memNext->Start >=
+ *pOffset + max_size))
break;
- pPacketMem = pPacketMem->next;
+ mem = mem->next;
}
/* Check for out-of-memory condition */
- if ((*pOffset + MaxPacketSize) >= USB_BDT_OFFSET)
+ if ((*pOffset + max_size) >= USB_BDT_OFFSET)
return false;
/*
* Allocate a new memory block, next to the last allocated block.
*/
- pPacketMemUseNew = usb_malloc();
- if (pPacketMemUseNew == NULL)
+ mem_useNew = usb_malloc();
+ if (mem_useNew == NULL)
return false;
/* Insert the block to the list of allocated blocks */
- if (pPacketMemUse == NULL)
+ if (mem_use == NULL)
{
- pPacketMemUse = pPacketMemUseNew;
- pPacketMemUse->next = NULL;
+ mem_use = mem_useNew;
+ mem_use->next = NULL;
}
else
{
- pPacketMemUseNew->next = pPacketMem->next;
- pPacketMem->next = pPacketMemUseNew;
+ mem_useNew->next = mem->next;
+ mem->next = mem_useNew;
}
/* Update block's metadata */
- pPacketMemUseNew->ep_addr = EndPoint;
- pPacketMemUseNew->Start = *pOffset;
- pPacketMemUseNew->Size = MaxPacketSize;
+ mem_useNew->ep_addr = EndPoint;
+ mem_useNew->Start = *pOffset;
+ mem_useNew->Size = max_size;
- *pPacketSize = MaxPacketSize;
+ *size = max_size;
return true;
}
/* Release a chunk of the packet memory (inside a block) */
-static void USB_ReleaseBuffer(int EndPoint)
+static void usb_free_buffer(int EndPoint)
{
- pack_mem_slot_t *pPacketMem, *pPacketMemPrev = NULL;
- pPacketMem = pPacketMemUse;
+ pack_mem_slot_t *mem, *memPrev = NULL;
+ mem = mem_use;
- while (pPacketMem != NULL)
+ while (mem != NULL)
{
- if (pPacketMem->ep_addr == EndPoint)
+ if (mem->ep_addr == EndPoint)
{
- if (UNLIKELY(pPacketMemPrev == NULL))
+ if (UNLIKELY(memPrev == NULL))
{
/* Free the first element of the list */
- pPacketMemUse = pPacketMemUse->next;
- usb_free(pPacketMem);
- pPacketMem = pPacketMemUse;
+ mem_use = mem_use->next;
+ usb_free(mem);
+ mem = mem_use;
continue;
}
- pPacketMemPrev->next = pPacketMem->next;
- usb_free(pPacketMem);
+ memPrev->next = mem->next;
+ usb_free(mem);
}
else
- pPacketMemPrev = pPacketMem;
- pPacketMem = pPacketMemPrev->next;
+ memPrev = mem;
+ mem = memPrev->next;
}
}
}
/* Convert logical EP address to physical EP address */
-static int USB_EpLogToPhysAdd(uint8_t ep_addr)
+static int usb_ep_logical_to_hw(uint8_t ep_addr)
{
int addr = (ep_addr & 0x0f) << 1;
return (ep_addr & 0x80) ? addr + 1 : addr;
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;
reg32_t *hw;
uint16_t Offset;
- uint32_t MaxPacketSizeTmp;
+ uint32_t size;
- EP = USB_EpLogToPhysAdd(epd->bEndpointAddress);
+ EP = usb_ep_logical_to_hw(epd->bEndpointAddress);
ep_hw = &ep_cnfg[EP];
if (enable)
* Allocate packet memory for EP buffer/s calculate actual size
* only for the OUT EPs.
*/
- MaxPacketSizeTmp = epd->wMaxPacketSize;
- if (!USB_AllocateBuffer(&Offset, &MaxPacketSizeTmp, EP))
+ size = epd->wMaxPacketSize;
+ if (!usb_alloc_buffer(&Offset, &size, EP))
return -USB_MEMORY_FULL;
/* Set EP status */
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);
+ usb_ep_low_level_config(EP, Offset, size);
/* Set EP Kind & enable */
switch (ep_hw->type)
EpCtrlClr_CTR_RX(hw);
}
/* Release buffer */
- USB_ReleaseBuffer(EP);
+ usb_free_buffer(EP);
ep_cnfg[EP].hw = NULL;
}
return 0;
*/
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_endpointRead_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_endpointRead(int ep, void *buffer, ssize_t size)
+{
+ int ep_num = usb_ep_logical_to_hw(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_endpointRead_complete);
+ while (!rx_done)
+ cpu_relax();
+
+ return rx_size;
+}
+
+static bool tx_done;
+static size_t tx_size;
+
+static void usb_endpointWrite_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_endpointWrite(int ep, const void *buffer, ssize_t size)
+{
+ int ep_num = usb_ep_logical_to_hw(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_endpointWrite_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;
}
return -USB_NODEV_ERROR;
InData = 0;
- USB_GetStallEP(USB_EpLogToPhysAdd(index), (bool *)&InData);
- __usb_ep_write(CTRL_ENP_IN, (uint8_t *)&InData, 2, USB_StatusHandler);
-
+ USB_GetStallEP(usb_ep_logical_to_hw(index), (bool *)&InData);
+ __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;
}
#define USB_BUFSIZE (128)
static uint8_t usb_cfg_buffer[USB_BUFSIZE];
+STATIC_ASSERT(USB_BUFSIZE < (1 << (sizeof(uint16_t) * 8)));
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 =
- usb_cpu_to_le16(p - usb_cfg_buffer);
+ ((UsbConfigDesc *)usb_cfg_buffer)->wTotalLength =
+ usb_cpu_to_le16((uint16_t)(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;
ep_cnfg[i].hw = NULL;
/* Initialize USB memory */
- for (i = 0; i < countof(PacketMemBuff); i++)
- PacketMemBuff[i].Size = 0;
+ for (i = 0; i < countof(memory_buffer); i++)
+ memory_buffer[i].Size = 0;
usb->BTABLE = USB_BDT_OFFSET;
- pPacketMemUse = NULL;
+ mem_use = NULL;
/* Endpoint initialization */
ret = usb_ep_configure(&USB_CtrlEpDescr0, true);
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_deviceRegister(UsbDevice *dev)
{
#if CONFIG_KERN
MOD_CHECK(proc);