Initialize and manage the USB Device Core statically and at run-time.
More...
Initialize and manage the USB Device Core statically and at run-time.
The Core of the USB Device has standard functions that are used to initialize and start the USB Device. These functions must be used before any class specific functions are called:
- Initialize the USB Device Controller, Hardware Driver and a specific USB Device using USBD_Initialize.
- Connect a specific USB Device to the USB Bus by calling USBD_Connect.
These two functions are accompanied by the USBD_Disconnect and USBD_Uninitialize functions. Use them to properly disconnect and uninitialize the device from the USB bus.
Static and Run-Time Configuration
The USB Device Core is statically configured using the USBD_Config_n.h file. However, for mass-production it is often required to be able to configure some USB Device settings at run-time (for example the serial number which needs to be unique for every single device). To achieve this, the following device configuration functions are part of the USBD_User_Device_n.c user code template. They enable user specific USB Control Endpoint 0 request handling. This allows the user to intercept all Control Endpoint 0 requests and handle them overriding the default USB Component handling:
Setup Packets on Control Endpoint 0
Setup packets sent to Control Endpoint 0 are received by the USB Device Core. The USB Device Core will call the USBD_Devicen_Endpoint0_SetupPacketReceived function and pass the setup packet to it. Depending on the return code of USBD_Devicen_Endpoint0_SetupPacketReceived, the USB Device Core either passes the processing to the Custom Class function if custom class is used and if message is addressed to a custom class by calling USBD_CustomClassn_Endpoint0_SetupPacketReceived function or continues to process the received setup packet itself. Depending on the return code of USBD_CustomClassn_Endpoint0_SetupPacketReceived, processing of the setup packet is either done or continues to be processed by USB Device Core.
USB Device Core will call USBD_Devicen_Endpoint0_SetupPacketProcessed and depending on return code it will call USBD_CustomClassn_Endpoint0_SetupPacketProcessed to inform the application that setup packet has been processed by USB Device Core.
If custom handling of request was used and request contains data stage, USB Device Core will call USBD_Devicen_Endpoint0_OutDataReceived and depending on return code it will call USBD_CustomClassn_Endpoint0_OutDataReceived after data expected by request was received, it will call USBD_Devicen_Endpoint0_InDataSent and depending on return code it will call USBD_CustomClassn_Endpoint0_InDataSent after data expected by request was sent.
Implementation
To create a USB Device:
User Code Templates
There are two user code templates available that help to configure the USB Device at run-time:
- USBD_User_Device_n.c contains all the callback functions that need to be implemented by the user.
- USBD_User_Device_SerNum_n.c is a code template that creates a custom serial number for a USB Device. This serial number will override the one that is set in the USBD_Config_n.h file.
User Code Template USBD_User_Device_n.c
The following source code can be used to implement the application specific behavior of a USB Device.
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
void USBD_Device%Instance%_Initialize (void) {
}
void USBD_Device%Instance%_Uninitialize (void) {
}
void USBD_Device%Instance%_VbusChanged (bool level) {
(void)level;
}
void USBD_Device%Instance%_Reset (void) {
}
void USBD_Device%Instance%_HighSpeedActivated (void) {
}
void USBD_Device%Instance%_Suspended (void) {
}
void USBD_Device%Instance%_Resumed (void) {
}
void USBD_Device%Instance%_ConfigurationChanged (uint8_t val) {
(void)val;
}
void USBD_Device%Instance%_EnableRemoteWakeup (void) {
}
void USBD_Device%Instance%_DisableRemoteWakeup (void) {
}
(void)buf;
(void)len;
case USB_REQUEST_STANDARD:
break;
case USB_REQUEST_CLASS:
break;
case USB_REQUEST_VENDOR:
break;
case USB_REQUEST_RESERVED:
break;
default:
break;
}
}
void USBD_Device%Instance%_Endpoint0_SetupPacketProcessed (
const USB_SETUP_PACKET *setup_packet) {
case USB_REQUEST_STANDARD:
break;
case USB_REQUEST_CLASS:
break;
case USB_REQUEST_VENDOR:
break;
case USB_REQUEST_RESERVED:
break;
default:
break;
}
}
(void)len;
}
(void)len;
}
User Code Template USBD_User_Device_SerNum_n.c
The following source code can be used to set an application specific serial number for the USB Device.
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
static bool handle_request;
static uint8_t ser_no_string_desc[32];
void USBD_Device%Instance%_Initialize (void) {
handle_request = false;
}
void USBD_Device%Instance%_Uninitialize (void) {
}
void USBD_Device%Instance%_VbusChanged (bool level) {
(void)level;
}
void USBD_Device%Instance%_Reset (void) {
}
void USBD_Device%Instance%_HighSpeedActivated (void) {
}
void USBD_Device%Instance%_Suspended (void) {
}
void USBD_Device%Instance%_Resumed (void) {
}
void USBD_Device%Instance%_ConfigurationChanged (uint8_t val) {
(void)val;
}
void USBD_Device%Instance%_EnableRemoteWakeup (void) {
}
void USBD_Device%Instance%_DisableRemoteWakeup (void) {
}
case USB_REQUEST_STANDARD:
if ((setup_packet->
bmRequestType.Dir == USB_REQUEST_DEVICE_TO_HOST) &&
(setup_packet->
bmRequestType.Recipient == USB_REQUEST_TO_DEVICE ) &&
(setup_packet->
bRequest == USB_REQUEST_GET_DESCRIPTOR) &&
((setup_packet->
wValue >> 8) == USB_STRING_DESCRIPTOR_TYPE) &&
((setup_packet->
wValue & 0xFFU) == 0x03U ) &&
(setup_packet->
wIndex == 0x0409U )) {
ser_no_string_desc[0] = 26U;
ser_no_string_desc[1] = USB_STRING_DESCRIPTOR_TYPE;
memcpy(&ser_no_string_desc[2], u"0001A0000001", 24);
*buf = ser_no_string_desc;
*len = 26U;
} else {
}
handle_request = true;
}
break;
case USB_REQUEST_CLASS:
break;
case USB_REQUEST_VENDOR:
break;
case USB_REQUEST_RESERVED:
break;
default:
break;
}
}
void USBD_Device%Instance%_Endpoint0_SetupPacketProcessed (
const USB_SETUP_PACKET *setup_packet) {
case USB_REQUEST_STANDARD:
break;
case USB_REQUEST_CLASS:
break;
case USB_REQUEST_VENDOR:
break;
case USB_REQUEST_RESERVED:
break;
default:
break;
}
}
(void)len;
}
(void)len;
if (handle_request) {
handle_request = false;
}
}