USB Component  Version 6.17.0
MDK Middleware for USB Device and Host Communication
Custom Class

Implement application specific behavior of a Custom Class USB Device. More...

Content

 User API
 User API reference of the Custom Device Class.
 
 Configuration
 Configuration of the USB Device Custom Class in µVision.
 

Description

Implement application specific behavior of a Custom Class USB Device.

The Custom Class in the USB Component may be used to implement any type of USB Device class.

Refer to:

The USB Component allows multiple instances of the Custom class. This feature may be used to create USB Composite Devices. Each Custom Class instance has separate files and interface functions:

This documentation uses n as a placeholder for the instance number 0 - 3. Most applications require only one instance of a Custom Class. For the first Custom Class instance the instance number is 0:

Software Structure

The handling of the Custom Class endpoint events is implemented in an USBD_CustomClassn_Endpointx_Event for every endpoint. Each endpoint (or pair of IN/OUT endpoints with the same endpoint number) uses an own thread in order to allow a parallel functionality of every interface.

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.

msc_inline_mscgraph_5

Implementation

To create an USB Device with a Custom Class:

User Code Templates

Two files are available to implement the application-specific behavior:

Both user code templates contain example code that can be used to demonstrate the features of the templates. Uncomment this code to see how it works on your target hardware.

USBD_User_CustomClass.c

/*------------------------------------------------------------------------------
* MDK Middleware - Component ::USB:Device:Custom Class
* Copyright (c) 2004-2020 Arm Limited (or its affiliates). All rights reserved.
*------------------------------------------------------------------------------
* Name: USBD_User_CustomClass_n.c
* Purpose: USB Device Custom Class User module
* Rev.: V6.7.4
*----------------------------------------------------------------------------*/
/*
* USBD_User_CustomClass_n.c is a code template for the Custom Class n
* class request handling. It allows user to handle all Custom Class class
* requests.
*
* Uncomment "Example code" lines to see example that receives data on
* Endpoint 1 OUT and echoes it back on Endpoint 1 IN.
* To try the example you also have to enable Bulk Endpoint 1 IN/OUT in Custom
* Class configuration in USBD_Config_CustomClass_n.h file.
*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "rl_usb.h"
#include "Driver_USBD.h"
//uint8_t classn_bulk_out_buf[64] = { 0 };
//uint8_t classn_bulk_in_buf [64] = { 0 };
// \brief Callback function called during USBD_Initialize to initialize the USB Custom class instance
// Handle Custom Class Initialization
}
// \brief Callback function called during USBD_Uninitialize to de-initialize the USB Custom class instance
// Handle Custom Class De-initialization
}
// \brief Callback function called upon USB Bus Reset signaling
// Handle USB Bus Reset Event
}
// \brief Callback function called when Endpoint Start was requested (by activating interface or configuration)
// \param[in] ep_addr endpoint address.
void USBD_CustomClassn_EndpointStart (uint8_t ep_addr) {
// Start communication on Endpoint
(void)ep_addr;
// // Example code start reception on Endpoint 1 OUT:
// if (ep_addr == USB_ENDPOINT_OUT(1)) {
// USBD_EndpointRead(0, USB_ENDPOINT_OUT(1), classn_bulk_out_buf, 64);
// }
}
// \brief Callback function called when Endpoint Stop was requested (by de-activating interface or activating configuration 0)
// \param[in] ep_addr endpoint address.
void USBD_CustomClassn_EndpointStop (uint8_t ep_addr) {
// Handle Endpoint communication stopped
(void)ep_addr;
}
// \brief Callback function called when Custom Class n received SETUP PACKET on Control Endpoint 0
// (this callback will be called only for Class Requests (USB_REQUEST_CLASS) if it was not processed
// previously by Device callback)
// \param[in] setup_packet pointer to received setup packet.
// \param[out] buf pointer to data buffer used for data stage requested by setup packet.
// \param[out] len pointer to number of data bytes in data stage requested by setup packet.
// \return usbdRequestStatus enumerator value indicating the function execution status
// \return usbdRequestNotProcessed:request was not processed; processing will be done by USB library
// \return usbdRequestOK: request was processed successfully (send Zero-Length Packet if no data stage)
// \return usbdRequestStall: request was processed but is not supported (stall Endpoint 0)
usbdRequestStatus USBD_CustomClassn_Endpoint0_SetupPacketReceived (const USB_SETUP_PACKET *setup_packet, uint8_t **buf, uint32_t *len) {
(void)buf;
(void)len;
switch (setup_packet->bmRequestType.Recipient) {
case USB_REQUEST_TO_DEVICE:
break;
case USB_REQUEST_TO_INTERFACE:
break;
case USB_REQUEST_TO_ENDPOINT:
break;
default:
break;
}
}
// \brief Callback function called when SETUP PACKET was processed by USB library
// (this callback will be called only for Class Requests (USB_REQUEST_CLASS) if it was not processed
// previously by Device callback nor by Custom Class callback)
// \param[in] setup_packet pointer to processed setup packet.
switch (setup_packet->bmRequestType.Recipient) {
case USB_REQUEST_TO_DEVICE:
break;
case USB_REQUEST_TO_INTERFACE:
break;
case USB_REQUEST_TO_ENDPOINT:
break;
default:
break;
}
}
// \brief Callback function called when Custom Class n received OUT DATA on Control Endpoint 0
// (this callback will be called only for Class Requests (USB_REQUEST_CLASS) if it was not processed
// previously by Device callback)
// \param[in] len number of received data bytes.
// \return usbdRequestStatus enumerator value indicating the function execution status
// \return usbdRequestNotProcessed:request was not processed; processing will be done by USB library
// \return usbdRequestOK: request was processed successfully (send Zero-Length Packet)
// \return usbdRequestStall: request was processed but is not supported (stall Endpoint 0)
// \return usbdRequestNAK: request was processed but the device is busy (return NAK)
usbdRequestStatus USBD_CustomClassn_Endpoint0_OutDataReceived (uint32_t len) {
(void)len;
}
// \brief Callback function called when Custom Class n sent IN DATA on Control Endpoint 0
// (this callback will be called only for Class Requests (USB_REQUEST_CLASS) if it was not processed
// previously by Device callback)
// \param[in] len number of sent data bytes.
// \return usbdRequestStatus enumerator value indicating the function execution status
// \return usbdRequestNotProcessed:request was not processed; processing will be done by USB library
// \return usbdRequestOK: request was processed successfully (return ACK)
// \return usbdRequestStall: request was processed but is not supported (stall Endpoint 0)
// \return usbdRequestNAK: request was processed but the device is busy (return NAK)
usbdRequestStatus USBD_CustomClassn_Endpoint0_InDataSent (uint32_t len) {
(void)len;
}
// \brief Callback function called when DATA was sent or received on Endpoint n
// \param[in] event event on Endpoint:
// - ARM_USBD_EVENT_OUT = data OUT received
// - ARM_USBD_EVENT_IN = data IN sent
void USBD_CustomClassn_Endpoint1_Event (uint32_t event) {
// uint32_t len;
// Handle Endpoint 1 events
if (event & ARM_USBD_EVENT_OUT) { // OUT event
// // Example code upon reception on Endpoint 1 OUT echo received data on
// // Endpoint 1 IN:
// // Get number of received data bytes
// len = USBD_EndpointReadGetResult(0, USB_ENDPOINT_OUT(1));
// // Copy received data bytes to transmit buffer
// memcpy(classn_bulk_in_buf, classn_bulk_out_buf, len);
// // Transmit back data bytes
// USBD_EndpointWrite(0, USB_ENDPOINT_IN(1) , classn_bulk_in_buf, len);
// // Restart reception on Endpoint 1 OUT:
// USBD_EndpointRead (0, USB_ENDPOINT_OUT(1), classn_bulk_out_buf, 64);
}
if (event & ARM_USBD_EVENT_IN) { // IN event
}
}
void USBD_CustomClassn_Endpoint2_Event (uint32_t event) {
// Handle Endpoint 2 events
(void)event;
}
void USBD_CustomClassn_Endpoint3_Event (uint32_t event) {
// Handle Endpoint 3 events
(void)event;
}
void USBD_CustomClassn_Endpoint4_Event (uint32_t event) {
// Handle Endpoint 4 events
(void)event;
}
void USBD_CustomClassn_Endpoint5_Event (uint32_t event) {
// Handle Endpoint 5 events
(void)event;
}
void USBD_CustomClassn_Endpoint6_Event (uint32_t event) {
// Handle Endpoint 6 events
(void)event;
}
void USBD_CustomClassn_Endpoint7_Event (uint32_t event) {
// Handle Endpoint 7 events
(void)event;
}
void USBD_CustomClassn_Endpoint8_Event (uint32_t event) {
// Handle Endpoint 8 events
(void)event;
}
void USBD_CustomClassn_Endpoint9_Event (uint32_t event) {
// Handle Endpoint 9 events
(void)event;
}
void USBD_CustomClassn_Endpoint10_Event (uint32_t event) {
// Handle Endpoint 10 events
(void)event;
}
void USBD_CustomClassn_Endpoint11_Event (uint32_t event) {
// Handle Endpoint 11 events
(void)event;
}
void USBD_CustomClassn_Endpoint12_Event (uint32_t event) {
// Handle Endpoint 12 events
(void)event;
}
void USBD_CustomClassn_Endpoint13_Event (uint32_t event) {
// Handle Endpoint 13 events
(void)event;
}
void USBD_CustomClassn_Endpoint14_Event (uint32_t event) {
// Handle Endpoint 14 events
(void)event;
}
void USBD_CustomClassn_Endpoint15_Event (uint32_t event) {
// Handle Endpoint 15 events
(void)event;
}

USBD_User_Device_n.c

/*------------------------------------------------------------------------------
* MDK Middleware - Component ::USB:Device
* Copyright (c) 2004-2020 Arm Limited (or its affiliates). All rights reserved.
*------------------------------------------------------------------------------
* Name: USBD_User_Device_n.c
* Purpose: USB Device User module
* Rev.: V6.8.2
*----------------------------------------------------------------------------*/
/*
* USBD_User_Device_n.c is a code template for the user specific
* Device events and Control Endpoint 0 requests handling. It allows user to
* handle all user level events as well as to intercept all Control Endpoint 0
* requests and handle them overriding the default USB Library handling.
*
* Uncomment "Example code" lines to override USB Device Descriptor.
*
* IMPORTANT NOTE!!!: Maximum packet size must not be set to less that 32 bytes!
*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "rl_usb.h"
//static const uint8_t devicen_dev_desc[] = {
// 18, /* bLength = 18 bytes */
// USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType = Device Desc */
// 0x00, 0x02, /* bcdUSB = 2.00 */
// 0x00, /* bDeviceClass = Defined in IF */
// 0x00, /* bDeviceSubClass = Defined in IF */
// 0x00, /* bDeviceProtocol = Defined in IF */
// 64, /* bMaxPacketSize0 = 64 bytes !!! Must be same as USBDn_MAX_PACKET0 in USBD_Config_n.c */
// 0x51, 0xC2, /* idVendor = 0xC251 */
// 0x01, 0x00, /* idProduct = 1 */
// 0x00, 0x01, /* bcdDevice = 1.00 */
// 0x01, /* iManufacturer = String1 */
// 0x02, /* iProduct = String2 */
// 0x03, /* iSerialNumber = String3 */
// 0x01 /* bNumConfigurations = 1 config */
//};
//static bool handle_request;
// \brief Callback function called during USBD_Initialize to initialize the USB Device
// Handle Device Initialization
// handle_request = false;
}
// \brief Callback function called during USBD_Uninitialize to de-initialize the USB Device
// Handle Device De-initialization
}
// \brief Callback function called when VBUS level changes
// \param[in] level current VBUS level
// - true: VBUS level is high
// - false: VBUS level is low
void USBD_Devicen_VbusChanged (bool level) {
(void)level;
}
// \brief Callback function called upon USB Bus Reset signaling
void USBD_Devicen_Reset (void) {
}
// \brief Callback function called when USB Bus speed was changed to high-speed
}
// \brief Callback function called when USB Bus goes into suspend mode (no bus activity for 3 ms)
}
// \brief Callback function called when USB Bus activity resumes
void USBD_Devicen_Resumed (void) {
}
// \brief Callback function called when Device was successfully enumerated
// \param[in] val current configuration value
// - value 0: not configured
// - value > 0: active configuration
(void)val;
}
// \brief Callback function called when Set Feature for Remote Wakeup comes over Control Endpoint 0
}
// \brief Callback function called when Clear Feature for Remote Wakeup comes over Control Endpoint 0
}
// \brief Callback function called when Device n received SETUP PACKET on Control Endpoint 0
// \param[in] setup_packet pointer to received setup packet.
// \param[out] buf pointer to data buffer used for data stage requested by setup packet.
// \param[out] len pointer to number of data bytes in data stage requested by setup packet.
// \return usbdRequestStatus enumerator value indicating the function execution status
// \return usbdRequestNotProcessed: request was not processed; processing will be done by USB library
// \return usbdRequestOK: request was processed successfully (send Zero-Length Packet if no data stage)
// \return usbdRequestStall: request was processed but is not supported (stall Endpoint 0)
usbdRequestStatus USBD_Devicen_Endpoint0_SetupPacketReceived (const USB_SETUP_PACKET *setup_packet, uint8_t **buf, uint32_t *len) {
(void)buf;
(void)len;
switch (setup_packet->bmRequestType.Type) {
case USB_REQUEST_STANDARD:
// // Example code handling Get Device Descriptor request:
// if ((setup_packet->bmRequestType.Dir == USB_REQUEST_DEVICE_TO_HOST) && // Request to get
// (setup_packet->bmRequestType.Recipient == USB_REQUEST_TO_DEVICE ) && // from device
// (setup_packet->bRequest == USB_REQUEST_GET_DESCRIPTOR) && // the descriptor
// ((setup_packet->wValue >> 8) == USB_DEVICE_DESCRIPTOR_TYPE) && // Device Descriptor Type
// (setup_packet->wIndex == 0U )) { // Index = 0
// *buf = (uint8_t *)((uint32_t)devicen_dev_desc);
// *len = sizeof (devicen_dev_desc);
// handle_request = true;
// return usbdRequestOK;
// }
break;
case USB_REQUEST_CLASS:
break;
case USB_REQUEST_VENDOR:
break;
case USB_REQUEST_RESERVED:
break;
default:
break;
}
}
// \brief Callback function called when SETUP PACKET was processed by USB library
// \param[in] setup_packet pointer to processed setup packet.
switch (setup_packet->bmRequestType.Type) {
case USB_REQUEST_STANDARD:
break;
case USB_REQUEST_CLASS:
break;
case USB_REQUEST_VENDOR:
break;
case USB_REQUEST_RESERVED:
break;
default:
break;
}
}
// \brief Callback function called when Device n received OUT DATA on Control Endpoint 0
// \param[in] len number of received data bytes.
// \return usbdRequestStatus enumerator value indicating the function execution status
// \return usbdRequestNotProcessed: request was not processed; processing will be done by USB library
// \return usbdRequestOK: request was processed successfully (send Zero-Length Packet)
// \return usbdRequestStall: request was processed but is not supported (stall Endpoint 0)
// \return usbdRequestNAK: request was processed but the device is busy (return NAK)
usbdRequestStatus USBD_Devicen_Endpoint0_OutDataReceived (uint32_t len) {
(void)len;
}
// \brief Callback function called when Device n sent IN DATA on Control Endpoint 0
// \param[in] len number of sent data bytes.
// \return usbdRequestStatus enumerator value indicating the function execution status
// \return usbdRequestNotProcessed: request was not processed; processing will be done by USB library
// \return usbdRequestOK: request was processed successfully (return ACK)
// \return usbdRequestStall: request was processed but is not supported (stall Endpoint 0)
// \return usbdRequestNAK: request was processed but the device is busy (return NAK)
usbdRequestStatus USBD_Devicen_Endpoint0_InDataSent (uint32_t len) {
(void)len;
// // Example code after Get Device Descriptor was sent:
// if (handle_request) { // If Device Descriptor was sent
// handle_request = false;
// return usbdRequestOK; // Acknowledge custom handled request
// }
}