Class Instance Concept
The USB classes available with the µC/USB-Device stack implement the concept of class instances. A class instance represents one function within a device. The function can be described by one interface or by a group of interfaces and belongs to a certain class.
Each USB class implementation has some configuration and functions in common based on the concept of class instance. The common configuration and functions are presented in Table - Constants and Functions Related to the Concept of Multiple Class Instances. In the column title 'Constants or Function', the placeholder XXXX
can be replaced by the name of the class: AUDIO (Audio for function names), CDC, HID, MSC, PHDC or VENDOR (Vendor for function names).
Constant or function | Description |
---|---|
USBD_XXXX_CFG_MAX_NBR_DEV | Configures the maximum number of class instances. |
USBD_XXXX_CFG_MAX_NBR_CFG | Configures the maximum number of configurations per device. During the class initialization, a created class instance will be added to one or more configurations. |
USBD_XXXX_Add() | Creates a new class instance. |
USBD_XXXX_CfgAdd() | Adds an existing class instance to the specified device configuration. |
In terms of code implementation, the class will declare a local global table that contains a class control structure. The size of the table is determined by the constant USBD_XXXX_CFG_MAX_NBR_DEV
. This class control structure is associated with one class instance and will contain certain information to manage the class instance. See the Class Instance Structures page for more details about this class control structure.
The following illustrations present several case scenarios. Each illustration is followed by a code listing showing the code corresponding to the case scenario. Figure - Multiple Class Instances - FS Device (1 Configuration with 1 Interface) represents a typical USB device. The device is Full-Speed (FS) and contains one single configuration. The function of the device is described by one interface composed of a pair of endpoints for the data communication. One class instance is created and it will allow you to manage the entire interface with its associated endpoint.
The code corresponding to Figure - Multiple Class Instances - FS Device (1 Configuration with 1 Interface) is shown in Listing - Multiple Class Instances - FS Device (1 Configuration with 1 Interface).
USBD_ERR err; CPU_INT08U class_0; USBD_XXXX_Init(&err); (1) if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } class_0 = USBD_XXXX_Add(&err); (2) if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } USBD_XXXX_CfgAdd(class_0, dev_nbr, cfg_0, &err); (3) if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ }
(1) Initialize the class. Any internal variables, structures, and class Real-Time Operating System (RTOS) port will be initialized.
(2) Create the class instance, class_0
. The function USBD_XXXX_Add()
allocates a class control structure associated to class_0
. Depending on the class, besides the parameter for an error code, USBD_XXXX_Add()
may have additional parameters representing class-specific information stored in the class control structure.
(3) Add the class instance, class_0
, to the specified configuration number, cfg_0
. USBD_XXXX_CfgAdd()
will create the interface 0 and its associated endpoints IN and OUT. As a result, the class instance encompasses the interface 0 and its endpoints. Any communication done on the interface 0 will use the class instance number, class_0
.
The code corresponding to Figure - Multiple Class Instances - HS/FS Device (2 Configurations and 1 Single Interface) is shown in Listing - Multiple Class Instances - HS/FS Device (2 Configurations and 1 Single Interface).
USBD_ERR err; CPU_INT08U class_0; USBD_XXXX_Init(&err); (1) if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } class_0 = USBD_XXXX_Add(&err); (2) if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } USBD_XXXX_CfgAdd(class_0, dev_nbr, cfg_0_fs, &err); (3) if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } USBD_XXXX_CfgAdd(class_0, dev_nbr, cfg_0_hs, &err); (4) if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ }
(1) Initialize the class. Any internal variables, structures, and class RTOS port will be initialized.
(2) Create the class instance, class_0
. The function USBD_XXXX_Add()
allocates a class control structure associated to class_0
. Depending on the class, besides the parameter for an error code, USBD_XXXX_Add()
may have additional parameters representing class-specific information stored in the class control structure.
(3) Add the class instance, class_0
, to the full-speed configuration, cfg_0_fs
. USBD_XXXX_CfgAdd()
will create the interface 0 and its associated endpoints IN and OUT. If the full-speed configuration is active, any communication done on the interface 0 will use the class instance number, class_0
.
(4) Add the class instance, class_0
, to the high-speed configuration, cfg_0_hs
.
In the case of the high-speed capable device presented in Figure - Multiple Class Instances - HS/FS Device (2 Configurations and 1 Single Interface), in order to enable the use of Device_Qualifier and Other_Speed_Configuration descriptors, the function USBD_CfgOtherSpeed()
should be called during the µC/USB-Device initialization. Listing - App_USBD_Init() Function presents the function App_USBD_Init()
defined in app_usbd.c
. This function shows an example of the µC/USB-Device initialization sequence. USBD_CfgOtherSpeed()
should be called after the creation of a high-speed and a full-speed configurations with USBD_CfgAdd()
. Listing - Use of USBD_CfgOtherSpeed() below shows the use of USBD_CfgOtherSpeed()
based on Listing - App_USBD_Init() Function. Error handling is omitted for clarity.
CPU_BOOLEAN App_USBD_Init (void) { CPU_INT08U dev_nbr; CPU_INT08U cfg_0_fs; CPU_INT08U cfg_0_hs; USBD_ERR err; ... (1) if (USBD_DrvCfg_<controller>.Spd == USBD_DEV_SPD_HIGH) { cfg_0_hs = USBD_CfgAdd(dev_nbr, (2) USBD_DEV_ATTRIB_SELF_POWERED, 100u, USBD_DEV_SPD_HIGH, "HS configuration", &err); } cfg_0_fs = USBD_CfgAdd(dev_nbr, (3) USBD_DEV_ATTRIB_SELF_POWERED, 100u, USBD_DEV_SPD_FULL, "FS configuration", &err); USBD_CfgOtherSpeed(dev_nbr, (4) cfg_0_hs, cfg_0_fs, &err); return (DEF_OK); }
(1) Refer to Listing - App_USBD_Init() Function for the beginning of the initialization.
(2) Add the high-speed configuration, cfg_0_hs
, to your high-speed capable device.
(3) Add the full-speed configuration, cfg_0_fs
, to your high-speed capable device.
(4) Associate the high-speed configuration cfg_0_hs
with its other-speed counterpart, cfg_0_fs
.
The code corresponding to Figure - Multiple Class Instances - FS Device (2 Configurations and Multiple Interfaces) is shown in Listing - Multiple Class Instances - FS Device (2 Configurations and Multiple Interfaces). The error handling is omitted for clarity.
USBD_ERR err; CPU_INT08U class_0; CPU_INT08U class_1; USBD_XXXX_Init(&err); (1) class_0 = USBD_XXXX_Add(&err); (2) class_1 = USBD_XXXX_Add(&err); (3) USBD_XXXX_CfgAdd(class_0, dev_nbr, cfg_0, &err); (4) USBD_XXXX_CfgAdd(class_1, dev_nbr, cfg_0, &err); (5) USBD_XXXX_CfgAdd(class_0, dev_nbr, cfg_1, &err); (6) USBD_XXXX_CfgAdd(class_1, dev_nbr, cfg_1, &err); (6)
(1) Initialize the class. Any internal variables, structures, and class RTOS port will be initialized.
(2) Create the class instance, class_0
. The function USBD_XXXX_Add()
allocates a class control structure associated to class_0
.
(3) Create the class instance, class_1
. The function USBD_XXXX_Add()
allocates another class control structure associated to class_1
.
(4) Add the class instance, class_0
, to the configuration, cfg_0
. USBD_XXXX_CfgAdd()
will create the interface 0, interface 1, alternate interfaces, and the associated endpoints IN and OUT. The class instance number, class_0
, will be used for any data communication on interface 0 or interface 1.
(5) Add the class instance, class_1
, to the configuration, cfg_0
. USBD_XXXX_CfgAdd()
will create the interface 2, interface 3 and their associated endpoints IN and OUT. The class instance number, class_1
, will be used for any data communication on interface 2 or interface 3.
(6) Add the same class instances, class_0
and class_1
, to the other configuration, cfg_1
.
You can refer to the Configuration Examples page for some configuration examples showing multiple class instances applied to composite devices. Composite devices use at least two different classes provided by the µC/USB-Device stack. The Composite High Speed USB Device section gives a concrete example based on Figure - Multiple Class Instances - HS/FS Device (2 Configurations and 1 Single Interface). See the Complex Composite High Speed USB Device section for a hybrid example that corresponds to Figure - Multiple Class Instances - HS/FS Device (2 Configurations and 1 Single Interface) and Figure - Multiple Class Instances - FS Device (2 Configurations and Multiple Interfaces).