USB Component  Version 6.6
MDK-Professional Middleware for USB Device and Host
 All Data Structures Functions Variables Enumerations Enumerator Groups Pages
Custom Class

USB Host functions to support Custom Class USB Devices. More...

Content

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

Description

USB Host functions to support Custom Class USB Devices.

The Custom Class in the USB Host Component is used for attaching USB Devices with a specific USB Class to your system. This can either be one of the standard classes that are not directly supported by the USB Middleware or a vendor specific class. Using these functions, you can add support for any USB Device class to the system.

Refer to:

Software Structure
The application starts the USB Host by calling USBH_Initialize. The USB Host Core will wait until an USB Custom Class device is attached to the system. As soon as this happens the Core will configure and initialize the device and it will be ready to be used by the application.

The transmit functions USBH_PipeSend and USBH_PipeReceive will be called by the user thread directly to communicate with the Custom Class device.

As soon as the Custom Class Device is detached from the system, the callback functions USBH_CustomClass_Unconfigure and USBH_CustomClass_Uninitialize signal the removal to the user application.

msc_inline_mscgraph_9

Implementation

To create an USB Host with support for the Custom class:

User Code Templates

There are two user code templates available that show how to create support for a Custom Class device:

  1. USBH_User_CustomClass.c shows in general how to use the Custom Class functions.
  2. USBH_PL2303.c is an actual implementation of the Custom Class functions to add support for Prolific's PL2303 UART to serial RS232 adapter.

User Code Template USBH_User_CustomClass.c
The following source code can be used to implement support for a Custom USB Device Class in the user application.

/*------------------------------------------------------------------------------
* MDK Middleware - Component ::USB:Host
* Copyright (c) 2004-2014 ARM Germany GmbH. All rights reserved.
*------------------------------------------------------------------------------
* Name: USBH_User_CustomClass.c
* Purpose: USB Host (USBH) - Custom Class User template
* Rev.: V6.2
*----------------------------------------------------------------------------*/
/*
* USBH_User_CustomClass.c is a code template for the Custom Class driver
* implementation on the USB Host stack.
* This implementation supports only one instance.
*
* The template implements 4 callback functions called by the USB Host core
* when device is connected or disconnected, these are:
* USBH_CustomClass_Configure
* USBH_CustomClass_Unconfigure
* USBH_CustomClass_Initialize
* USBH_CustomClass_Uninitialize
*
* First to enable USB Host Controller (if not already enabled) call:
* USBH_Initialize (ctrl_num);
*/
#include <stdint.h>
#include "rl_usb.h"
// Interface class, subclass and protocol of the device that is supported
#define CUSTOM_CLASS_IF_CLASS USB_DEVICE_CLASS_VENDOR_SPECIFIC
#define CUSTOM_CLASS_IF_SUBCLASS 0
#define CUSTOM_CLASS_IF_PROTOCOL 0
uint8_t USBH_CustomClass_Ctrl = 0; // Controller number used for USB transfers
USBH_PIPE *USBH_CustomClass_Pipes[8] = { 0 }; // Pointers to Pipes
/************************** Class Driver Functions ****************************/
uint8_t USBH_CustomClass_Configure (const USBH_DEV *ptr_dev, const USB_DEVICE_DESCRIPTOR *ptr_dev_desc, const USB_CONFIGURATION_DESCRIPTOR *ptr_cfg_desc) {
USBH_PIPE *ptr_pipe;
USB_INTERFACE_DESCRIPTOR *ptr_if_desc;
USB_ENDPOINT_DESCRIPTOR *ptr_ep_desc;
uint8_t num, i;
USBH_CustomClass_Ctrl = ptr_dev->ctrl; // Store controller number
ptr_if_desc = (USB_INTERFACE_DESCRIPTOR *)((uint32_t)ptr_cfg_desc + ptr_cfg_desc->bLength);
num = ptr_if_desc->bNumEndpoints; // Number of endpoints
// Check if this is the supported device (VID, PID)
// Vendor ID value: ptr_dev_desc->idVendor
// Product ID value: ptr_dev_desc->idProduct
switch (ptr_if_desc->bInterfaceClass) {
case CUSTOM_CLASS_IF_CLASS: // Interface class
switch (ptr_if_desc->bInterfaceSubClass) {
case CUSTOM_CLASS_IF_SUBCLASS: // Interface subclass
switch (ptr_if_desc->bInterfaceProtocol) {
case CUSTOM_CLASS_IF_PROTOCOL: // Interface protocol
// Create Pipes
ptr_ep_desc = (USB_ENDPOINT_DESCRIPTOR *)((uint32_t)ptr_if_desc + ptr_if_desc->bLength);
i = 0;
while (num--) {
ptr_pipe = USBH_PipeCreate (ptr_dev->ctrl, ptr_dev->dev_addr, ptr_dev->dev_speed, 0, 0, ptr_ep_desc->bEndpointAddress, ptr_ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK, ptr_ep_desc->wMaxPacketSize & 0x7FF, ptr_ep_desc->bInterval);
if (!ptr_pipe) {
// If creation of pipe failed delete previously created pipes
for (i = 0; i < 8; i++) {
if (USBH_CustomClass_Pipes[i]) {
USBH_PipeDelete (USBH_CustomClass_Ctrl, USBH_CustomClass_Pipes[i]);
USBH_CustomClass_Pipes[i] = NULL;
}
}
return 0xFF;
}
USBH_CustomClass_Pipes[i++] = ptr_pipe;
ptr_ep_desc++;
}
return 0; // Device connected and configured
// Only single instance supported
// so it's instance index is 0
}
break;
}
break;
}
return 0xFF; // Device not handled
}
usbStatus USBH_CustomClass_Unconfigure (uint8_t instance) {
uint8_t i;
USBH_CustomClass_Ctrl = 0;
for (i = 0; i < 8; i++) {
if (USBH_CustomClass_Pipes[i]) {
USBH_PipeDelete (USBH_CustomClass_Ctrl, USBH_CustomClass_Pipes[i]);
USBH_CustomClass_Pipes[i] = NULL;
}
}
return usbOK;
}
usbStatus USBH_CustomClass_Initialize (uint8_t instance) {
// Add code for initializing device
return usbOK;
}
usbStatus USBH_CustomClass_Uninitialize (uint8_t instance) {
// Add code for de-initializing device
return usbOK;
}

User Code Template USBH_PL2303.c
The following source code implements support for Prolific's PL2303 UART to serial RS232 adapter using the Custom Class functions.

/*------------------------------------------------------------------------------
* MDK Middleware - Component ::USB:Host
* Copyright (c) 2004-2014 ARM Germany GmbH. All rights reserved.
*------------------------------------------------------------------------------
* Name: USBH_PL2303.c
* Purpose: USB Host (USBH) - Custom Class - Prolific PL2303 USB to serial
* RS232 adapter driver
* Rev.: V6.2
*----------------------------------------------------------------------------*/
/*
* USBH_PL2303.c is a Prolific PL2303 USB to serial RS232 adapter driver
* for USB Host stack implemented as USB Host Custom Class driver.
* Prolific PL2303 USB to serial RS232 adapter is similar to the CDC device
* but using vendor specific class device with interface containing
* 1 Bulk IN, 1 Bulk OUT and 1 Interrupt IN Endpoints.
* This implementation supports only one instance.
*
* The driver implements 4 callback functions called by the USB Host core
* when device is connected or disconnected, these are:
* USBH_CustomClass_Configure
* USBH_CustomClass_Unconfigure
* USBH_CustomClass_Initialize
* USBH_CustomClass_Uninitialize
*
* First to enable USB Host Controller (if not already enabled) call:
* USBH_Initialize (ctrl_num);
*/
#include <stdint.h>
#include "rl_usb.h"
// Interface class, subclass and protocol of the device that is supported
#define CUSTOM_CLASS_IF_CLASS USB_DEVICE_CLASS_VENDOR_SPECIFIC
#define CUSTOM_CLASS_IF_SUBCLASS 0
#define CUSTOM_CLASS_IF_PROTOCOL 0
uint8_t USBH_CustomClass_Ctrl = 0; // Controller number used for USB transfers
USBH_PIPE *USBH_CustomClass_Pipes[8] = { 0 }; // Pointers to Pipes
/************************** Class Driver Functions ****************************/
uint8_t USBH_CustomClass_Configure (const USBH_DEV *ptr_dev, const USB_DEVICE_DESCRIPTOR *ptr_dev_desc, const USB_CONFIGURATION_DESCRIPTOR *ptr_cfg_desc) {
USBH_PIPE *ptr_pipe;
USB_INTERFACE_DESCRIPTOR *ptr_if_desc;
USB_ENDPOINT_DESCRIPTOR *ptr_ep_desc;
uint8_t num, i;
USBH_CustomClass_Ctrl = ptr_dev->ctrl; // Store controller number
ptr_if_desc = (USB_INTERFACE_DESCRIPTOR *)((uint32_t)ptr_cfg_desc + ptr_cfg_desc->bLength);
num = ptr_if_desc->bNumEndpoints; // Number of endpoints
// Supported device: - Prolific PL2303 (VID = 0x067B, PID = 0x2303)
if ((ptr_dev_desc->idVendor != 0x067B) || (ptr_dev_desc->idProduct != 0x2303))
return 0xFF;
switch (ptr_if_desc->bInterfaceClass) {
case CUSTOM_CLASS_IF_CLASS: // Interface class
switch (ptr_if_desc->bInterfaceSubClass) {
case CUSTOM_CLASS_IF_SUBCLASS: // Interface subclass
switch (ptr_if_desc->bInterfaceProtocol) {
case CUSTOM_CLASS_IF_PROTOCOL: // Interface protocol
// Create Pipes
ptr_ep_desc = (USB_ENDPOINT_DESCRIPTOR *)((uint32_t)ptr_if_desc + ptr_if_desc->bLength);
i = 0;
while (num--) {
ptr_pipe = USBH_PipeCreate (ptr_dev->ctrl, ptr_dev->dev_addr, ptr_dev->dev_speed, 0, 0, ptr_ep_desc->bEndpointAddress, ptr_ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK, ptr_ep_desc->wMaxPacketSize & 0x7FF, ptr_ep_desc->bInterval);
if (!ptr_pipe) {
// If creation of pipe failed delete previously created pipes
for (i = 0; i < 8; i++) {
if (USBH_CustomClass_Pipes[i]) {
USBH_PipeDelete (USBH_CustomClass_Ctrl, USBH_CustomClass_Pipes[i]);
USBH_CustomClass_Pipes[i] = NULL;
}
}
return 0xFF;
}
USBH_CustomClass_Pipes[i++] = ptr_pipe;
ptr_ep_desc++;
}
return 0; // Device connected and configured
// Only single instance supported
// so it's instance index is 0
}
break;
}
break;
}
return 0xFF; // Device not handled
}
usbStatus USBH_CustomClass_Unconfigure (uint8_t instance) {
uint8_t i;
USBH_CustomClass_Ctrl = 0;
for (i = 0; i < 8; i++) {
if (USBH_CustomClass_Pipes[i]) {
USBH_PipeDelete (USBH_CustomClass_Ctrl, USBH_CustomClass_Pipes[i]);
USBH_CustomClass_Pipes[i] = NULL;
}
}
return usbOK;
}
usbStatus USBH_CustomClass_Initialize (uint8_t instance) {
USB_SETUP_PACKET setup_packet;
uint8_t buf[8];
// Custom PL2303 initialization
setup_packet.bmRequestType.Dir = USB_REQUEST_DEVICE_TO_HOST;
setup_packet.bmRequestType.Type = USB_REQUEST_VENDOR;
setup_packet.bmRequestType.Recipient= USB_REQUEST_TO_DEVICE;
setup_packet.bRequest = 1;
setup_packet.wValue = U16_LE(0x8484);
setup_packet.wIndex = U16_LE(0);
setup_packet.wLength = U16_LE(1);
if (USBH_ControlTransfer (USBH_CustomClass_Ctrl, &setup_packet, buf, 1) != usbOK) return usbClassErrorCustom;
setup_packet.bmRequestType.Dir = USB_REQUEST_HOST_TO_DEVICE;
setup_packet.wValue = U16_LE(0x0404);
if (USBH_ControlTransfer (USBH_CustomClass_Ctrl, &setup_packet, buf, 1) != usbOK) return usbClassErrorCustom;
setup_packet.bmRequestType.Dir = USB_REQUEST_DEVICE_TO_HOST;
setup_packet.wValue = U16_LE(0x8484);
if (USBH_ControlTransfer (USBH_CustomClass_Ctrl, &setup_packet, buf, 1) != usbOK) return usbClassErrorCustom;
setup_packet.wValue = U16_LE(0x8383);
if (USBH_ControlTransfer (USBH_CustomClass_Ctrl, &setup_packet, buf, 1) != usbOK) return usbClassErrorCustom;
setup_packet.wValue = U16_LE(0x8484);
if (USBH_ControlTransfer (USBH_CustomClass_Ctrl, &setup_packet, buf, 1) != usbOK) return usbClassErrorCustom;
setup_packet.bmRequestType.Dir = USB_REQUEST_HOST_TO_DEVICE;
setup_packet.wValue = U16_LE(0x0404);
setup_packet.wIndex = U16_LE(1);
setup_packet.wLength = U16_LE(0);
if (USBH_ControlTransfer (USBH_CustomClass_Ctrl, &setup_packet, NULL, 0) != usbOK) return usbClassErrorCustom;
setup_packet.bmRequestType.Dir = USB_REQUEST_DEVICE_TO_HOST;
setup_packet.wValue = U16_LE(0x8484);
setup_packet.wIndex = U16_LE(0);
setup_packet.wLength = U16_LE(1);
if (USBH_ControlTransfer (USBH_CustomClass_Ctrl, &setup_packet, buf, 1) != usbOK) return usbClassErrorCustom;
setup_packet.wValue = U16_LE(0x8383);
if (USBH_ControlTransfer (USBH_CustomClass_Ctrl, &setup_packet, buf, 1) != usbOK) return usbClassErrorCustom;
setup_packet.bmRequestType.Dir = USB_REQUEST_HOST_TO_DEVICE;
setup_packet.wValue = U16_LE(0);
setup_packet.wIndex = U16_LE(1);
setup_packet.wLength = U16_LE(0);
if (USBH_ControlTransfer (USBH_CustomClass_Ctrl, &setup_packet, NULL, 0) != usbOK) return usbClassErrorCustom;
setup_packet.wValue = U16_LE(1);
setup_packet.wIndex = U16_LE(0);
if (USBH_ControlTransfer (USBH_CustomClass_Ctrl, &setup_packet, NULL, 0) != usbOK) return usbClassErrorCustom;
setup_packet.wValue = U16_LE(2);
setup_packet.wIndex = U16_LE(0x44);
if (USBH_ControlTransfer (USBH_CustomClass_Ctrl, &setup_packet, NULL, 0) != usbOK) return usbClassErrorCustom;
// Initial CDC SetLineCoding request: Set 9600 baud, 8 data bits, 1 stop bit, no parity
setup_packet.bmRequestType.Dir = USB_REQUEST_HOST_TO_DEVICE;
setup_packet.bmRequestType.Type = USB_REQUEST_CLASS;
setup_packet.bmRequestType.Recipient= USB_REQUEST_TO_INTERFACE;
setup_packet.bRequest = 0x20;
setup_packet.wValue = U16_LE(0);
setup_packet.wIndex = U16_LE(0);
setup_packet.wLength = U16_LE(7);
*((uint32_t *)&buf[0]) = U32_LE(9600);// Data terminal rate in bits per second = 9600 baud
buf[4] = 0; // Number of stop bits = 1
buf[5] = 0; // Parity bit type = None
buf[6] = 8; // Number of data bits = 8
if (USBH_ControlTransfer (USBH_CustomClass_Ctrl, &setup_packet, buf, 7) != usbOK) return usbClassErrorCustom;
return usbOK;
}
usbStatus USBH_CustomClass_Uninitialize (uint8_t instance) {
return usbOK;
}