mirror of
https://github.com/eclipse-threadx/rtos-docs.git
synced 2026-02-06 02:52:14 +08:00
Merge pull request #45 from ayedm1/update_usbx_device_stack_doc
Update usbx device stack doc
This commit is contained in:
@@ -29,7 +29,7 @@ The relationship between the USB layers is as follows:
|
||||
- Responsive technical support
|
||||
- Multiple class support
|
||||
- Multiple class instances
|
||||
- Integration of classes with ThreadX, FileX, and NetX Duo
|
||||
- Integration of classes with ThreadX, FileX and NetX Duo
|
||||
- Support for USB devices with multiple configurations
|
||||
- Support for USB composite devices
|
||||
- Support for USB power management
|
||||
|
||||
@@ -36,7 +36,6 @@ The following is a list of several important files in the repository.
|
||||
|
||||
* ***ux_api.h***: This C header file contains all system equates, data structures, and service prototypes.
|
||||
* ***ux_port.h***: This C header file contains all development-tool-specific data definitions and structures.
|
||||
* ***ux.lib***: This is the binary version of the USBX C library. It is distributed with the standard package.
|
||||
* ***demo_usbx.c***: The C file containing a simple USBX demo
|
||||
|
||||
All filenames are in lower-case. This naming convention makes it easier to convert the commands to Unix development platforms.
|
||||
@@ -55,13 +54,23 @@ You will also find instructions for building the USBX library on the front page
|
||||
|
||||
The following general instructions apply to virtually any installation:
|
||||
|
||||
with RTOS:
|
||||
|
||||
1. Use the same directory in which you previously installed ThreadX on the host hard drive. All USBX names are unique and will not interfere with the previous USBX installation.
|
||||
1. Add a call to ***ux_system_initialize*** at or near the beginning of ***tx_application_define***. This is where the USBX resources are initialized.
|
||||
1. Add a call to ***ux_device_stack_initialize*.**
|
||||
1. Add one or more calls to initialize the required USBX classes (either host and/or devices classes)
|
||||
1. Add one or more calls to initialize the device controller available in the system.
|
||||
1. It may be required to modify the tx_low_level_initialize.c file to add low-level hardware initialization and interrupt vector routing. This is specific to the hardware platform and will not be discussed here.|
|
||||
1. Compile application source code and link with the USBX and ThreadX run time libraries (FileX and/or NetX Duo may also be required if the USB storage class and/or USB network classes are to be compiled in), ux.a (or ux.lib) and tx.a (or tx.lib). The resulting can be downloaded to the target and executed!
|
||||
2. Add a call to ***ux_system_initialize*** at or near the beginning of ***tx_application_define***. This is where the USBX resources are initialized.
|
||||
3. Add a call to ***ux_device_stack_initialize*.**
|
||||
4. Add one or more calls to initialize the required USBX classes (either host and/or devices classes)
|
||||
5. Add one or more calls to initialize the device controller available in the system.
|
||||
6. It may be required to modify the tx_low_level_initialize.c file to add low-level hardware initialization and interrupt vector routing. This is specific to the hardware platform and will not be discussed here.|
|
||||
7. Compile application source code and link with the USBX and ThreadX run time libraries (FileX and/or NetX Duo may also be required if the USB storage class and/or USB network classes are to be compiled in), ux.a (or ux.lib) and tx.a (or tx.lib). The resulting can be downloaded to the target and executed!
|
||||
|
||||
with Standalone (without RTOS):
|
||||
1. All USBX names are unique and will not interfere with the previous USBX installation.
|
||||
2. Add a call to ***ux_system_initialize*** This is where the USBX resources are initialized.
|
||||
3. Add a call to ***ux_device_stack_initialize*.**
|
||||
4. Add one or more calls to initialize the required USBX classes (either host and/or devices classes)
|
||||
5. Add one or more calls to initialize the device controller available in the system.
|
||||
6. Add a call to ***ux_system_tasks_run*.** in main function while(1).
|
||||
|
||||
## Configuration Options
|
||||
|
||||
@@ -69,45 +78,52 @@ There are several configuration options for building the USBX library. All optio
|
||||
|
||||
The list below details each configuration option.
|
||||
|
||||
| Configuration Option | Description |
|
||||
| --- | --- |
|
||||
| **UX_PERIODIC_RATE** | This value represents how many ticks per seconds for a specific hardware platform. The default is 1000 indicating 1 tick per millisecond. |
|
||||
| **UX_THREAD_STACK_SIZE** | This value is the size of the stack in bytes for the USBX threads. It can be typically 1024 bytes or 2048 bytes depending on the processor used and the host controller. |
|
||||
| **UX_THREAD_PRIORITY_ENUM** | This is the ThreadX priority value for the USBX enumeration threads that monitors the bus topology. |
|
||||
| **UX_THREAD_PRIORITY_CLASS** | This is the ThreadX priority value for the standard USBX threads. |
|
||||
| **UX_THREAD_PRIORITY_KEYBOARD** | This is the ThreadX priority value for the USBX HID keyboard class. |
|
||||
| **UX_THREAD_PRIORITY_DCD** | This is the ThreadX priority value for the device controller thread. |
|
||||
| **UX_NO_TIME_SLICE** | This value actually defines the time slice that will be used for threads. For example, if defined to 0, the ThreadX target port does not use time slices. |
|
||||
| **UX_MAX_SLAVE_CLASS_DRIVER** | This is the maximum number of USBX classes that can be registered via ux_device_stack_class_register. |
|
||||
| **UX_MAX_SLAVE_LUN** | This value represents the current number of SCSI logical units represented in the device storage class driver. |
|
||||
| **UX_SLAVE_CLASS_STORAGE_INCLUDE_MMC** | If defined, the storage class will handle Multi-Media Commands (MMC) that is, DVD-ROM. |
|
||||
| **UX_DEVICE_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES** | This value represents the number of NetX packets in the CDC-ECM class' packet pool. The default is 16. |
|
||||
| **UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH** | This value represents the maximum number of bytes received on a control endpoint in the device stack. The default is 256 bytes but can be reduced in memory constraint environments. |
|
||||
| **UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH** | This value represents the maximum length in bytes of a HID report. |
|
||||
| **UX_DEVICE_CLASS_HID_MAX_EVENTS_QUEUE** | This value represents the maximum number of HID reports that can be queued at once. |
|
||||
| **UX_SLAVE_REQUEST_DATA_MAX_LENGTH** | This value represents the maximum number of bytes received on a bulk endpoint in the device stack. The default is 4096 bytes but can be reduced in memory constraint environments. |
|
||||
| **UX_DEVICE_BIDIRECTIONAL_ENDPOINT_SUPPORT** | If defined, the device side enables bi-directional-endpoints support, e.g., endpoints addressed 0x01 and 0x81. Otherwise (the default case), endpoint number must be unique in same configuration. Note the feature must be used with compatible DCD and peripheral. |
|
||||
| Configuration Option | Description |
|
||||
| ----------------------------------------------- | ----------- |
|
||||
| **UX_PERIODIC_RATE** | This value represents how many ticks per seconds for a specific hardware platform. The default is 1000 indicating 1 tick per millisecond. |
|
||||
| **UX_THREAD_STACK_SIZE** | This value is the size of the stack in bytes for the USBX threads. It can be typically 1024 bytes or 2048 bytes depending on the processor used and the host controller. |
|
||||
| **UX_THREAD_PRIORITY_CLASS** | This is the ThreadX priority value for the standard USBX threads. |
|
||||
| **UX_THREAD_PRIORITY_DCD** | This is the ThreadX priority value for the device controller thread. |
|
||||
| **UX_ALIGN_MIN** | This value represents minimal allocated memory alignment in number of bytes. The default is UX_ALIGN_8 (0x07) to align allocated memory to 8 bytes. |
|
||||
| **UX_ENFORCE_SAFE_ALIGNMENT** | This value forces the memory allocation scheme to enforce alignment of memory with the UX_SAFE_ALIGN field. |
|
||||
| **UX_NO_TIME_SLICE** | This value actually defines the time slice that will be used for threads. For example, if defined to 0, the ThreadX target port does not use time slices. |
|
||||
| **UX_MAX_SLAVE_CLASS_DRIVER** | This value is the maximum number of classes in the device stack that can be loaded by USBX. |
|
||||
| **UX_MAX_SLAVE_INTERFACES** | This value is the maximum number of interfaces in the device framework. |
|
||||
| **UX_DEVICE_ENDPOINT_BUFFER_OWNER** | This value represents the endpoint buffer owner. 0 The default, endpoint buffer is managed by core stack. Each endpoint takes UX_SLAVE_REQUEST_DATA_MAX_LENGTH bytes, 1 Endpoint buffer managed by classes. In this case not all endpoints consume UX_SLAVE_REQUEST_DATA_MAX_LENGTH bytes |
|
||||
| **UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH** | This value represents the maximum number of bytes received on a control endpoint in the device stack. The default is 256 bytes but can be reduced in memory constrained environments. |
|
||||
| **UX_SLAVE_REQUEST_DATA_MAX_LENGTH** | This value represents the maximum number of bytes that can be received or transmitted on any endpoint. This value cannot be less than the maximum packet size of any endpoint. The default is 4096 bytes but can be reduced in memory constrained environments. For cd-rom support in the storage class, this value cannot be less than 2048. |
|
||||
| **UX_DEVICE_BIDIRECTIONAL_ENDPOINT_SUPPORT** | If defined, the device side enables bi-directional-endpoints support, e.g., endpoints addressed 0x01 and 0x81. Otherwise (the default case), endpoint number must be unique in same configuration. Note the feature must be used with compatible DCD and peripheral. |
|
||||
| **UX_DEVICE_ALTERNATE_SETTING_SUPPORT_DISABLE** | This macro disables interface alternate setting support. |
|
||||
| **UX_DEVICE_INITIALIZE_FRAMEWORK_SCAN_DISABLE** | This macro disables device framework scan, where max number of endpoints (except EP0) and max number of interfaces are calculated at runtime, as a base to allocate memory for interfaces and endpoints structures and their buffers. Undefined, the following two macros must be defined to initialize memory structures. |
|
||||
| **UX_MAX_DEVICE_ENDPOINTS** | This value represents max number of endpoints (except EP0) activated at the same time. Works if UX_DEVICE_INITIALIZE_FRAMEWORK_SCAN_DISABLE is defined. |
|
||||
| **UX_MAX_DEVICE_INTERFACES** | This value represents max number of interfaces activated at the same time. Works if UX_DEVICE_INITIALIZE_FRAMEWORK_SCAN_DISABLE is defined. |
|
||||
| **UX_NAME_REFERENCED_BY_POINTER** | Defined, the _name in structs are referenced by pointer instead of by contents. By default the _name is an array of string that saves characters, the contents are compared to confirm match. If referenced by pointer the address pointer to const string is saved, the pointers are compared to confirm match. |
|
||||
| **UX_DEVICE_SIDE_ONLY** | This value will only enable the device side of USBX. |
|
||||
| **UX_STANDALONE** | This macro will enable the standalone mode of USBX. |
|
||||
| **UX_DEBUG_LOG_SIZE** | This value represents the size of the log pool. |
|
||||
| **UX_ENABLE_ASSERT** | This enables the assert checks inside USBX. |
|
||||
| **UX_ENABLE_ERROR_CHECKING** | This option enables the basic USBX error checking. This define is typically used when the application is debugging and removed after the application is fully debugged. |
|
||||
|
||||
## Source Code Tree
|
||||
|
||||
The USBX files are provided in several directories.
|
||||
|
||||

|
||||

|
||||
|
||||
In order to make the files recognizable by their names, the following convention has been adopted:
|
||||
|
||||
| File Suffix Name | File description |
|
||||
| ----------------- | ----------------------------------------- |
|
||||
| ux_host_stack | usbx host stack core files |
|
||||
| ux_host_class | usbx host stack classes files |
|
||||
| ux_hcd | usbx host stack controller driver files |
|
||||
| ux_device_stack | usbx device stack core files |
|
||||
| ux_device_class | usbx device stack classes files |
|
||||
| ux_dcd | usbx device stack controller driver files |
|
||||
| ux_otg | usbx otg controller driver related files |
|
||||
| ux_pictbridge | usbx pictbridge files |
|
||||
| ux_utility | usbx utility functions |
|
||||
| demo_usbx | demonstration files for USBX |
|
||||
| ux_host_stack | usbx host stack core files |
|
||||
| ux_host_class | usbx host stack classes files |
|
||||
| ux_hcd | usbx host stack controller driver files |
|
||||
| ux_device_stack | usbx device stack core files |
|
||||
| ux_device_class | usbx device stack classes files |
|
||||
| ux_dcd | usbx device stack controller driver files |
|
||||
| ux_otg | usbx otg controller driver related files |
|
||||
| ux_pictbridge | usbx pictbridge files |
|
||||
| ux_utility | usbx utility functions |
|
||||
| demo_usbx | demonstration files for USBX |
|
||||
|
||||
## Initialization of USBX resources
|
||||
|
||||
@@ -117,26 +133,24 @@ The following function initializes USBX memory resources with 128 K of regular m
|
||||
|
||||
```c
|
||||
/* Initialize USBX Memory */
|
||||
ux_system_initialize(memory_pointer,(128*1024),UX_NULL,0);
|
||||
ux_system_initialize(memory_pointer, (128*1024), UX_NULL, 0);
|
||||
```
|
||||
|
||||
The prototype for the ux_system_initialize is as follows:
|
||||
|
||||
```c
|
||||
UINT ux_system_initialize(VOID *regular_memory_pool_start,
|
||||
ULONG regular_memory_size,
|
||||
VOID *cache_safe_memory_pool_start,
|
||||
ULONG cache_safe_memory_size);
|
||||
ULONG regular_memory_size,
|
||||
VOID *cache_safe_memory_pool_start,
|
||||
ULONG cache_safe_memory_size);
|
||||
```
|
||||
|
||||
Input parameters:
|
||||
Where:
|
||||
|
||||
| Parameter | Description |
|
||||
| ---------------------------------- | --------------------------------------- |
|
||||
| VOID *regular_memory_pool_start | Beginning of the regular memory pool |
|
||||
| ULONG regular_memory_size | Size of the regular memory pool |
|
||||
| VOID *cache_safe_memory_pool_start | Beginning of the cache safe memory pool |
|
||||
| ULONG cache_safe_memory_size | Size of the cache safe memory pool |
|
||||
- *regular_memory_pool_start*: Beginning of the regular memory pool.
|
||||
- *regular_memory_size*: Size of the regular memory pool.
|
||||
- *cache_safe_memory_pool_start*: Beginning of the cache safe memory pool.
|
||||
- *cache_safe_memory_size*: Size of the cache safe memory pool.
|
||||
|
||||
Not all systems require the definition of cache safe memory. In such a system, the values passed during the initialization for the memory pointer will be set to UX_NULL and the size of the pool to 0. USBX will then use the regular memory pool in lieu of the cache safe pool.
|
||||
|
||||
@@ -147,8 +161,7 @@ In a system where the regular memory is not cache safe and a controller requires
|
||||
USBX can be terminated by releasing its resources. Prior to terminating usbx, all classes and controller resources need to be terminated properly. The following function uninitializes USBX memory resources:
|
||||
|
||||
```c
|
||||
/* Unitialize USBX Resources */
|
||||
|
||||
/* Uninitialize USBX Resources */
|
||||
ux_system_uninitialize();
|
||||
```
|
||||
|
||||
@@ -158,6 +171,27 @@ The prototype for the ux_system_initialize is as follows:
|
||||
UINT ux_system_uninitialize(VOID);
|
||||
```
|
||||
|
||||
## Task Run of USBX resources
|
||||
|
||||
This function runs USB system tasks, including possible tasks for host, device and OTG.
|
||||
|
||||
```c
|
||||
|
||||
while(1)
|
||||
{
|
||||
#if defined(UX_DEVICE_STANDALONE)
|
||||
ux_system_tasks_run();
|
||||
#endif
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
The prototype for the ux_system_tasks_run is as follows:
|
||||
|
||||
```c
|
||||
UINT ux_system_tasks_run(VOID);
|
||||
```
|
||||
|
||||
## Definition of USB Device Controller
|
||||
|
||||
Only one USB device controller can be defined at any time to operate in device mode. The application initialization file should contain this definition. The following line performs the definition of a generic usb controller:
|
||||
@@ -169,17 +203,14 @@ ux_dcd_controller_initialize(0x7BB00000, 0, 0xB7A00000);
|
||||
The USB device initialization has the following prototype:
|
||||
|
||||
```c
|
||||
UINT ux_dcd_controller_initialize(ULONG dcd_io,
|
||||
ULONG dcd_irq, ULONG dcd_vbus_address);
|
||||
UINT ux_dcd_controller_initialize(ULONG dcd_io, ULONG dcd_irq, ULONG dcd_vbus_address);
|
||||
```
|
||||
|
||||
with the following parameters:
|
||||
Where:
|
||||
|
||||
| Parameter | Description |
|
||||
| ------------------------ | -------------------------------- |
|
||||
| ULONG dcd_io | Address of the controller IO |
|
||||
| ULONG dcd_irq | Interrupt used by the controller |
|
||||
| ULONG dcd_vbus_address | Address of the VBUS GPIO |
|
||||
- *dcd_io*: Address of the controller IO.
|
||||
- *dcd_irq*: Interrupt used by the controller.
|
||||
- *dcd_vbus_address*: Address of the VBUS GPIO .
|
||||
|
||||
The following example is the initialization of USBX in device mode with the storage device class and a generic controller:
|
||||
|
||||
@@ -189,11 +220,11 @@ The following example is the initialization of USBX in device mode with the stor
|
||||
ux_system_initialize(memory_pointer,(128*1024), 0, 0);
|
||||
|
||||
/* The code below is required for installing the device portion of USBX */
|
||||
status = ux_device_stack_initialize(&device_framework_high_speed,
|
||||
DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED, &device_framework_full_speed,
|
||||
DEVICE_FRAMEWORK_LENGTH_FULL_SPEED, &string_framework,
|
||||
STRING_FRAMEWORK_LENGTH, &language_id_framework,
|
||||
LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
|
||||
status = ux_device_stack_initialize(&device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
|
||||
&device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
|
||||
&string_framework, STRING_FRAMEWORK_LENGTH,
|
||||
&language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,
|
||||
UX_NULL);
|
||||
|
||||
/* If status equals UX_SUCCESS, installation was successful. */
|
||||
|
||||
@@ -205,13 +236,12 @@ storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage
|
||||
storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_block_length = 512;
|
||||
storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_type = 0;
|
||||
storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_removable_flag = 0x80;
|
||||
storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read = tx_demo_thread_flash_media_read;
|
||||
storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write = tx_demo_thread_flash_media_write;
|
||||
storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status = tx_demo_thread_flash_media_status;
|
||||
storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read = demo_thread_flash_media_read;
|
||||
storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write = demo_thread_flash_media_write;
|
||||
storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status = demo_thread_flash_media_status;
|
||||
|
||||
/* Initialize the device storage class. The class is connected with interface 0 */
|
||||
status = ux_device_stack_class_register(ux_system_slave_class_storage_name ux_device_class_storage_entry,
|
||||
ux_device_class_storage_thread,0, (VOID *)&storage_parameter);
|
||||
status = ux_device_stack_class_register(ux_system_slave_class_storage_name ux_device_class_storage_entry, ux_device_class_storage_thread, 0, (VOID *)&storage_parameter);
|
||||
|
||||
/* Register the device controllers available in this system */
|
||||
status = ux_dcd_controller_initialize(0x7BB00000, 0, 0xB7A00000);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
# Mandatory fields.
|
||||
title: Chapter 3 - Functional Components of USBX Device Stack
|
||||
description: This chapter contains a description of the high performance USBX embedded USB device stack from a functional perspective.
|
||||
---
|
||||
@@ -11,19 +10,18 @@ This chapter contains a description of the high performance USBX embedded USB de
|
||||
## Execution Overview
|
||||
|
||||
USBX for the device is composed of several components.
|
||||
|
||||
- Initialization
|
||||
- Application interface calls
|
||||
- USB Device Classes
|
||||
- USB Device Stack
|
||||
- Device controller
|
||||
- VBUS manager
|
||||
- [Initialization](#initialization)
|
||||
- [Application interface calls](#application_interface_calls)
|
||||
- [USB Device Classes](#usb_device_classes)
|
||||
- [USB Device Stack](#usb_device_stack)
|
||||
- [USB Device controller](#usb_device_controller)
|
||||
- [VBUS manager](#vbus_manager)
|
||||
|
||||
The following diagram illustrates the USBX Device stack.
|
||||
|
||||

|
||||

|
||||
|
||||
### Initialization
|
||||
## initialization
|
||||
|
||||
In order to activate USBX, the function ***ux_system_initialize*** must be called. This function initializes the memory resources of USBX.
|
||||
|
||||
@@ -31,7 +29,7 @@ In order to activate USBX device facilities, the function ***ux_device_stack_ini
|
||||
|
||||
It is up to the application initialization to activate the USB device controller and one or more USB classes. Contrary to the USB host side, the device side can have only one USB controller driver running at any time. When the classes have been registered to the stack and the device controller(s) initialization function has been called, the bus is active and the stack will reply to bus reset and host enumeration commands.
|
||||
|
||||
### Application Interface Calls
|
||||
## application_interface_calls
|
||||
|
||||
There are two levels of APIs in USBX.
|
||||
|
||||
@@ -40,30 +38,30 @@ There are two levels of APIs in USBX.
|
||||
|
||||
Normally, a USBX application should not have to call any of the USB device stack APIs. Most applications will only access the USB Class APIs.
|
||||
|
||||
### USB Device Classes
|
||||
## usb_device_classes
|
||||
|
||||
The Class APIs are very specific to each USB class. Most of the common APIs for USB classes provided services such as opening/closing a device and reading from or writing to a device.
|
||||
|
||||
#### Storage Class
|
||||
### Storage Class
|
||||
|
||||
The storage class is in charge of answering storage class specific control requests and handling storage class protocol commands. Refer to USB Device Storage Class in Chapter 5 for more information.
|
||||
|
||||
#### CDC Class
|
||||
### CDC Class
|
||||
|
||||
The CDC class is in charge of answering CDC class specific control requests and offering ways to communicate with host through data pipes. Following functionalities are supported now:
|
||||
* CDC-ACM: communicate with host as a serial device
|
||||
* CDC-ECM: communicate with host as an ethernet device
|
||||
Refer to USB Device CDC-ACM Class and USB Device CDC-ECM Class in Chapter 5 for more information.
|
||||
|
||||
#### HID Class
|
||||
### HID Class
|
||||
|
||||
The HID class is in charge of answering the HID class specific control requests and offering ways to communicate host with HID class specific reports. Refer to USB Device HID Class in Chapter 5 for more information.
|
||||
|
||||
#### Custom Class
|
||||
### Custom Class
|
||||
|
||||
For advanced developers, it's possible to create more customized class, to answering customized control requests and handling customized protocol on data pipes. Note such class may also require specific customization on host side, too.
|
||||
|
||||
## USB Device Stack
|
||||
## usb_device_stack
|
||||
The device stack APIs are responsible for the registration of USBX device components such as classes and the device framework.
|
||||
|
||||
### Device Framework
|
||||
@@ -163,7 +161,7 @@ To support additional languages, simply add the language code double-byte defini
|
||||
|
||||
*Developing International Software for Windows 95 and Windows NT, Nadine Kano, Eclipse Foundation Press, Redmond WA*
|
||||
|
||||
## Device controller
|
||||
## usb_device_controller
|
||||
|
||||
The device controller driver (DCD) interoperates USB Device Stack operations to hardware actions. Normally, a USBX application should not have to call device controller APIs, except initialization function. When the device controller initialization function is called, the bus is active and the stack will reply to bus reset and host enumeration commands through device controller driver.
|
||||
|
||||
@@ -174,7 +172,7 @@ Here are some possible hardware which USB Device Stack can operate on:
|
||||
* Reneses chip with USB device controller
|
||||
* Other chip with USB device controller, etc.
|
||||
|
||||
## VBUS Manager
|
||||
## vbus_manager
|
||||
|
||||
In most USB device designs, VBUS is not part of the USB Device core but rather connected to an external GPIO, which monitors the line signal.
|
||||
|
||||
|
||||
@@ -5,7 +5,30 @@ description: Learn about the USBX Device Services.
|
||||
|
||||
# Description of USBX Device Services
|
||||
|
||||
### ux_device_stack_alternate_setting_get
|
||||
This chapter contains a description of USBX device stack services in alphabetic order.
|
||||
|
||||
The USBX device stack API functions available to the application are as follows.
|
||||
- [ux_device_stack_alternate_setting_get](#ux_device_stack_alternate_setting_get)
|
||||
- [ux_device_stack_alternate_setting_set](#ux_device_stack_alternate_setting_set)
|
||||
- [ux_device_stack_class_register](#ux_device_stack_class_register)
|
||||
- [ux_device_stack_class_unregister](#ux_device_stack_class_unregister)
|
||||
- [ux_device_stack_configuration_get](#ux_device_stack_configuration_get)
|
||||
- [ux_device_stack_configuration_set](#ux_device_stack_configuration_set)
|
||||
- [ux_device_stack_descriptor_send](#ux_device_stack_descriptor_send)
|
||||
- [ux_device_stack_disconnect](#ux_device_stack_disconnect)
|
||||
- [ux_device_stack_endpoint_stall](#ux_device_stack_endpoint_stall)
|
||||
- [ux_device_stack_host_wakeup](#ux_device_stack_host_wakeup)
|
||||
- [ux_device_stack_initialize](#ux_device_stack_initialize)
|
||||
- [ux_device_stack_interface_delete](#ux_device_stack_interface_delete)
|
||||
- [ux_device_stack_interface_get](#ux_device_stack_interface_get)
|
||||
- [ux_device_stack_interface_set](#ux_device_stack_interface_set)
|
||||
- [ux_device_stack_interface_start](#ux_device_stack_interface_start)
|
||||
- [ux_device_stack_transfer_request](#ux_device_stack_transfer_request)
|
||||
- [ux_device_stack_transfer_abort](#ux_device_stack_transfer_abort)
|
||||
- [ux_device_stack_uninitialize](#ux_device_stack_uninitialize)
|
||||
- [ux_device_stack_microsoft_extension_register](#ux_device_stack_microsoft_extension_register)
|
||||
|
||||
## ux_device_stack_alternate_setting_get
|
||||
|
||||
Get current alternate setting for an interface value
|
||||
|
||||
@@ -21,7 +44,7 @@ This function is used by the USB host to obtain the current alternate setting fo
|
||||
|
||||
### Input Parameter
|
||||
|
||||
- *Interface_value*: Interface value for which the current alternate setting is queried
|
||||
- *interface_value*: Interface value for which the current alternate setting is queried
|
||||
|
||||
### Return Values
|
||||
|
||||
@@ -40,7 +63,7 @@ status = ux_device_stack_alternate_setting_get(interface_value);
|
||||
/* If status equals UX_SUCCESS, the operation was successful. */
|
||||
```
|
||||
|
||||
### ux_device_stack_alternate_setting_set
|
||||
## ux_device_stack_alternate_setting_set
|
||||
|
||||
Set current alternate setting for an interface value
|
||||
|
||||
@@ -76,7 +99,6 @@ The function starts status stage of the control transfer in background, and retu
|
||||
|
||||
```c
|
||||
ULONG interface_value;
|
||||
|
||||
ULONG alternate_setting_value;
|
||||
|
||||
/* The following example illustrates this service. */
|
||||
@@ -85,7 +107,7 @@ status = ux_device_stack_alternate_setting_set(interface_value, alternate_settin
|
||||
/* If status equals UX_SUCCESS, the operation was successful. */
|
||||
```
|
||||
|
||||
### ux_device_stack_class_register
|
||||
## ux_device_stack_class_register
|
||||
|
||||
Register a new USB device class
|
||||
|
||||
@@ -130,11 +152,10 @@ UINT status;
|
||||
/* The following example illustrates this service. */
|
||||
|
||||
/* Initialize the device storage class. The class is connected with interface 1 */
|
||||
status = ux_device_stack_class_register(_ux_system_slave_class_storage_name ux_device_class_storage_entry,
|
||||
1, 1, (VOID *)¶meter);
|
||||
status = ux_device_stack_class_register(_ux_system_slave_class_storage_name ux_device_class_storage_entry, 1, 1, (VOID *)¶meter);
|
||||
```
|
||||
|
||||
### ux_device_stack_class_unregister
|
||||
## ux_device_stack_class_unregister
|
||||
|
||||
Unregister a USB device class
|
||||
|
||||
@@ -176,7 +197,7 @@ status = ux_device_stack_class_unregister(_ux_system_slave_class_storage_name, u
|
||||
/* If status equals UX_SUCCESS, the operation was successful. */
|
||||
```
|
||||
|
||||
### ux_device_stack_configuration_get
|
||||
## ux_device_stack_configuration_get
|
||||
|
||||
Get the current configuration
|
||||
|
||||
@@ -209,7 +230,7 @@ status = ux_device_stack_configuration_get();
|
||||
/* If status equals UX_SUCCESS, the operation was successful. */
|
||||
```
|
||||
|
||||
### ux_device_stack_configuration_set
|
||||
## ux_device_stack_configuration_set
|
||||
|
||||
Set the current configuration
|
||||
|
||||
@@ -245,7 +266,7 @@ status = ux_device_stack_configuration_set(configuration_value);
|
||||
/* If status equals UX_SUCCESS, the operation was successful. */
|
||||
```
|
||||
|
||||
### ux_device_stack_descriptor_send
|
||||
## ux_device_stack_descriptor_send
|
||||
|
||||
Send a descriptor to the host
|
||||
|
||||
@@ -334,7 +355,7 @@ Request endpoint Stall condition
|
||||
### Prototype
|
||||
|
||||
```c
|
||||
UINT ux_device_stack_endpoint_stall(UX_SLAVE_ENDPOINT*endpoint);
|
||||
UINT ux_device_stack_endpoint_stall(UX_SLAVE_ENDPOINT *endpoint);
|
||||
```
|
||||
|
||||
### Description
|
||||
@@ -363,7 +384,7 @@ status = ux_device_stack_endpoint_stall(endpoint);
|
||||
/* If status equals UX_SUCCESS, the operation was successful. */
|
||||
```
|
||||
|
||||
### ux_device_stack_host_wakeup
|
||||
## ux_device_stack_host_wakeup
|
||||
|
||||
Wake up the host
|
||||
|
||||
@@ -400,7 +421,7 @@ status = ux_device_stack_host_wakeup();
|
||||
/* If status equals UX_SUCCESS, the operation was successful. */
|
||||
```
|
||||
|
||||
### ux_device_stack_initialize
|
||||
## ux_device_stack_initialize
|
||||
|
||||
Initialize USB device stack
|
||||
|
||||
@@ -415,8 +436,8 @@ UINT ux_device_stack_initialize(
|
||||
UCHAR *string_framework,
|
||||
ULONG string_framework_length,
|
||||
UCHAR *language_id_framework,
|
||||
ULONG language_id_framework_length),
|
||||
UINT (*ux_system_slave_change_function)(ULONG)));
|
||||
ULONG language_id_framework_length,
|
||||
UINT (*ux_system_slave_change_function)(ULONG));
|
||||
```
|
||||
|
||||
### Description
|
||||
@@ -541,23 +562,23 @@ UINT status;
|
||||
|
||||
/* The code below is required for installing the device portion of USBX.
|
||||
There is no call back for device status change in this example. */
|
||||
status = ux_device_stack_initialize(&device_framework_high_speed,
|
||||
DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED, &device_framework_full_speed,
|
||||
DEVICE_FRAMEWORK_LENGTH_FULL_SPEED, &string_framework,
|
||||
STRING_FRAMEWORK_LENGTH, &language_id_framework,
|
||||
LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
|
||||
status = ux_device_stack_initialize(&device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
|
||||
&device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
|
||||
&string_framework, STRING_FRAMEWORK_LENGTH,
|
||||
&language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,
|
||||
UX_NULL);
|
||||
|
||||
/* If status equals UX_SUCCESS, initialization was successful. */
|
||||
```
|
||||
|
||||
### ux_device_stack_interface_delete
|
||||
## ux_device_stack_interface_delete
|
||||
|
||||
Delete a stack interface
|
||||
|
||||
### Prototype
|
||||
|
||||
```c
|
||||
UINT ux_device_stack_interface_delete(UX_SLAVE_INTERFACE*interface);
|
||||
UINT ux_device_stack_interface_delete(UX_SLAVE_INTERFACE *ux_interface);
|
||||
```
|
||||
|
||||
### Description
|
||||
@@ -566,7 +587,7 @@ This function is called when an interface should be removed. An interface is eit
|
||||
|
||||
### Input Parameter
|
||||
|
||||
- *interface*: Pointer to the interface to remove.
|
||||
- *ux_interface*: Pointer to the interface to remove.
|
||||
|
||||
### Return Value
|
||||
|
||||
@@ -583,7 +604,7 @@ status = ux_device_stack_interface_delete(interface);
|
||||
/* If status equals UX_SUCCESS, the operation was successful. */
|
||||
```
|
||||
|
||||
### ux_device_stack_interface_get
|
||||
## ux_device_stack_interface_get
|
||||
|
||||
Get the current interface value
|
||||
|
||||
@@ -621,7 +642,7 @@ status = ux_device_stack_interface_get(interface_value);
|
||||
/* If status equals UX_SUCCESS, the operation was successful. */
|
||||
```
|
||||
|
||||
### ux_device_stack_interface_set
|
||||
## ux_device_stack_interface_set
|
||||
|
||||
Change the alternate setting of the interface
|
||||
|
||||
@@ -654,26 +675,25 @@ This function starts status stage of the control transfer in background, and ret
|
||||
### Example
|
||||
|
||||
```c
|
||||
UCHAR * device_framework
|
||||
UCHAR *device_framework
|
||||
ULONG device_framework_length;
|
||||
ULONG alternate_setting_value;
|
||||
UINT status;
|
||||
UINT status;
|
||||
|
||||
/* The following example illustrates this service. */
|
||||
status = ux_device_stack_interface_set(device_framework,
|
||||
device_framework_length, alternate_setting_value);
|
||||
status = ux_device_stack_interface_set(device_framework, device_framework_length, alternate_setting_value);
|
||||
|
||||
/* If status equals UX_SUCCESS, the operation was successful. */
|
||||
```
|
||||
|
||||
### ux_device_stack_interface_start
|
||||
## ux_device_stack_interface_start
|
||||
|
||||
Start search for a class to own an interface instance
|
||||
|
||||
### Prototype
|
||||
|
||||
```c
|
||||
UINT ux_device_stack_interface_start(UX_SLAVE_INTERFACE*interface);
|
||||
UINT ux_device_stack_interface_start(UX_SLAVE_INTERFACE *ux_interface);
|
||||
```
|
||||
|
||||
### Description
|
||||
@@ -686,7 +706,7 @@ This function is not blocking and returns immediately.
|
||||
|
||||
### Input Parameter
|
||||
|
||||
- *interface*: Pointer to the interface created.
|
||||
- *ux_interface*: Pointer to the interface created.
|
||||
|
||||
### Return Values
|
||||
|
||||
@@ -704,7 +724,7 @@ status = ux_device_stack_interface_start(interface);
|
||||
/* If status equals UX_SUCCESS, the operation was successful. */
|
||||
```
|
||||
|
||||
### ux_device_stack_transfer_request
|
||||
## ux_device_stack_transfer_request
|
||||
|
||||
Request to transfer data to the host
|
||||
|
||||
@@ -766,7 +786,7 @@ while(total_length) {
|
||||
}
|
||||
```
|
||||
|
||||
### ux_device_stack_transfer_abort
|
||||
## ux_device_stack_transfer_abort
|
||||
|
||||
Cancel a transfer request
|
||||
|
||||
@@ -803,9 +823,9 @@ status = ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_BUS_RESET)
|
||||
/* If status equals UX_SUCCESS, the operation was successful. */
|
||||
```
|
||||
|
||||
### ux_device_stack_uninitialize
|
||||
## ux_device_stack_uninitialize
|
||||
|
||||
Unitialize stack
|
||||
Uninitialize stack
|
||||
|
||||
### Prototype
|
||||
|
||||
@@ -815,7 +835,7 @@ UINT ux_device_stack_uninitialize();
|
||||
|
||||
### Description
|
||||
|
||||
This function is called when an application needs to unitialize the USBX device stack – all device stack resources are freed, and return immediately. This should be called after all classes have been unregistered via ux_device_stack_class_unregister.
|
||||
This function is called when an application needs to uninitialize the USBX device stack – all device stack resources are freed, and return immediately. This should be called after all classes have been unregistered via ux_device_stack_class_unregister.
|
||||
|
||||
### Parameters
|
||||
|
||||
@@ -824,3 +844,154 @@ None
|
||||
### Return Value
|
||||
|
||||
**UX_SUCCESS** (0x00) This operation was successful.
|
||||
|
||||
## ux_device_stack_microsoft_extension_register
|
||||
|
||||
Registers the Microsoft extensions
|
||||
|
||||
### Prototype
|
||||
|
||||
```c
|
||||
UINT ux_device_stack_microsoft_extension_register(
|
||||
ULONG vendor_request,
|
||||
UINT (*vendor_request_function)(ULONG, ULONG, ULONG, ULONG, UCHAR *, ULONG *))
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
This function registers the Microsoft extensions to support vendor commands before the device is configured.
|
||||
|
||||
### Parameters
|
||||
|
||||
- *vendor_request*: Vendor Command.
|
||||
- *vendor_request_function*: Vendor Command application Callback.
|
||||
|
||||
### Return Value
|
||||
|
||||
**UX_SUCCESS** (0x00) This operation was successful.
|
||||
|
||||
### Example
|
||||
|
||||
```c
|
||||
#define UX_DEMO_VENDOR_REQUEST 0x54
|
||||
|
||||
/* MS extensions. */
|
||||
status = _ux_device_stack_microsoft_extension_register(UX_DEMO_VENDOR_REQUEST, pima_device_vendor_request);
|
||||
|
||||
|
||||
UINT pima_device_vendor_request(ULONG request, ULONG request_value, ULONG request_index, ULONG request_length,
|
||||
UCHAR *transfer_request_buffer,
|
||||
ULONG *transfer_request_length)
|
||||
{
|
||||
UINT status;
|
||||
ULONG length;
|
||||
|
||||
/* Do some sanity check. The request must be our vendor request. */
|
||||
if (request != UX_TEST_VENDOR_REQUEST)
|
||||
|
||||
/* Do not proceed. */
|
||||
return(UX_ERROR);
|
||||
|
||||
/* Check the wIndex value. Values can be :
|
||||
0x0001 : Genre
|
||||
0x0004 : Extended compatible ID
|
||||
0x0005 : Extended properties */
|
||||
switch (request_index)
|
||||
{
|
||||
|
||||
case 0x0001 :
|
||||
|
||||
/* Not sure what this is for. Windows does not seem to request this. Drop it. */
|
||||
status = UX_ERROR;
|
||||
break;
|
||||
|
||||
case 0x0004 :
|
||||
case 0x0005 :
|
||||
|
||||
/* Length to return. */
|
||||
length = UX_MIN(0x28, request_length);
|
||||
|
||||
/* Length check. */
|
||||
UX_ASSERT(*transfer_request_length >= length);
|
||||
|
||||
/* At least length should be returned. */
|
||||
if (length < 4)
|
||||
{
|
||||
status = UX_ERROR;
|
||||
break;
|
||||
}
|
||||
status = UX_SUCCESS;
|
||||
|
||||
/* Return the length. */
|
||||
*transfer_request_length = length;
|
||||
|
||||
/* Reset returned bytes. */
|
||||
ux_utility_memory_set(transfer_request_buffer, 0, length);
|
||||
|
||||
/* Build the descriptor to be returned. This is not a composite descriptor. Single MTP.
|
||||
First dword is length of the descriptor. */
|
||||
ux_utility_long_put(transfer_request_buffer, 0x0028);
|
||||
length -= 4;
|
||||
|
||||
/* Then the version. fixed to 0x0100. */
|
||||
if (length < 2)
|
||||
break;
|
||||
ux_utility_short_put(transfer_request_buffer + 4, 0x0100);
|
||||
length -= 2;
|
||||
|
||||
/* Then the descriptor ID. Fixed to 0x0004. */
|
||||
if (length < 2)
|
||||
break;
|
||||
ux_utility_short_put(transfer_request_buffer + 6, 0x0004);
|
||||
length -= 2;
|
||||
|
||||
/* Then the bcount field. Fixed to 0x0001. */
|
||||
if (length < 1)
|
||||
break;
|
||||
*(transfer_request_buffer + 8) = 0x01;
|
||||
length -= 1;
|
||||
|
||||
/* Reset the next 7 bytes. */
|
||||
if (length < 7)
|
||||
break;
|
||||
ux_utility_memory_set(transfer_request_buffer + 9, 0x00, 7);
|
||||
length -= 7;
|
||||
|
||||
/* Last byte of header is the interface number, here 0. */
|
||||
if (length < 1)
|
||||
break;
|
||||
*(transfer_request_buffer + 16) = 0x00;
|
||||
length -= 1;
|
||||
|
||||
/* First byte of descriptor is set to 1. */
|
||||
if (length < 1)
|
||||
break;
|
||||
*(transfer_request_buffer + 17) = 0x01;
|
||||
length -= 1;
|
||||
|
||||
/* Reset the next 8 + 8 + 6 bytes. */
|
||||
if (length < (8+8+6))
|
||||
break;
|
||||
ux_utility_memory_set(transfer_request_buffer + 18, 0x00, (8 + 8 + 6));
|
||||
length -= 8+8+6;
|
||||
|
||||
/* Set the compatible ID to MTP. */
|
||||
if (length < 3)
|
||||
break;
|
||||
ux_utility_memory_copy(transfer_request_buffer + 18, "MTP", 3);
|
||||
length -= 3;
|
||||
|
||||
/* We are done here. */
|
||||
status = UX_SUCCESS;
|
||||
break;
|
||||
|
||||
default :
|
||||
status = UX_ERROR;
|
||||
break;
|
||||
|
||||
}
|
||||
/* Return status to device stack. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,19 +9,15 @@ This guide provides comprehensive information about USBX, the high performance U
|
||||
|
||||
It is intended for the embedded real-time software developer. The developer should be familiar with standard real-time operating system functions, the USB specification, and the C programming language.
|
||||
|
||||
For technical information related to USB, see the USB specification and USB Class specifications that can be downloaded at https://www.USB.org/developers.
|
||||
For technical information related to USB, see the USB specification and USB Class specifications that can be downloaded at https://www.usb.org/developers.
|
||||
|
||||
## Organization
|
||||
|
||||
- [**Chapter 1**](usbx-device-stack-1.md) - contains an introduction to USBX
|
||||
|
||||
- [**Chapter 2**](usbx-device-stack-2.md) - gives the basic steps to install and use USBX with your ThreadX application
|
||||
|
||||
- [**Chapter 3**](usbx-device-stack-3.md) - describes the functional components of the USBX device stack
|
||||
|
||||
- [**Chapter 4**](usbx-device-stack-4.md) - describes the USBX device stack services
|
||||
|
||||
- [**Chapter 5**](usbx-device-stack-5.md) - describes each USBX device class including their APIs
|
||||
- [**Chapter 1**](usbx-device-stack-1.md) - contains an introduction to USBX.
|
||||
- [**Chapter 2**](usbx-device-stack-2.md) - gives the basic steps to install and use USBX.
|
||||
- [**Chapter 3**](usbx-device-stack-3.md) - describes the functional components of the USBX device stack.
|
||||
- [**Chapter 4**](usbx-device-stack-4.md) - describes the USBX device stack services.
|
||||
- [**Chapter 5**](usbx-device-stack-5.md) - describes each USBX device class including their APIs.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -9,8 +9,10 @@ This document is a supplement to the USBX Device Stack User Guide. It contains d
|
||||
|
||||
## Organization
|
||||
|
||||
- **Chapter 1** contains an introduction to USBX
|
||||
- [**Chapter 2**](usbx-device-stack-supplemental-2.md) USBX Host Classes API
|
||||
- [**Chapter 3**](usbx-device-stack-supplemental-3.md) USBX DPUMP Class Considerations
|
||||
- [**Chapter 4**](usbx-device-stack-supplemental-4.md) USBX Pictbridge implementation
|
||||
- [**Chapter 5**](usbx-device-stack-supplemental-5.md) USBX OTG
|
||||
- [**Chapter 1**](usbx-device-stack-supplemental-1.md) contains an introduction to USBX.
|
||||
- [**Chapter 2**](usbx-device-stack-supplemental-2.md) USBX Device Classes APIs.
|
||||
- [**Chapter 3**](usbx-device-stack-supplemental-3.md) USBX DPUMP Class Considerations.
|
||||
- [**Chapter 4**](usbx-device-stack-supplemental-4.md) USBX Pictbridge implementation.
|
||||
- [**Chapter 5**](usbx-device-stack-supplemental-5.md) USBX OTG.
|
||||
- [**Chapter 7**](usbx-device-stack-supplemental-6.md) USBX Implement controller driver (DCD).
|
||||
- [**Chapter 8**](usbx-device-stack-supplemental-7.md) USBX Implement device class modules.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -51,20 +51,10 @@ Unlike other USBX device implementations, the Pictbridge application does not ne
|
||||
|
||||
```C
|
||||
/* Initialize the Pictbridge string components. */
|
||||
ux_utility_memory_copy
|
||||
(pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_vendor_name,
|
||||
"ExpressLogic",13);
|
||||
|
||||
ux_utility_memory_copy
|
||||
(pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_product_name,
|
||||
"EL_Pictbridge_Camera",21);
|
||||
|
||||
ux_utility_memory_copy
|
||||
(pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_serial_no, "ABC_123",7);
|
||||
|
||||
ux_utility_memory_copy
|
||||
(pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_dpsversions,
|
||||
"1.0 1.1",7);
|
||||
ux_utility_memory_copy(pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_vendor_name, "ExpressLogic",13);
|
||||
ux_utility_memory_copy(pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_product_name, "EL_Pictbridge_Camera",21);
|
||||
ux_utility_memory_copy(pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_serial_no, "ABC_123",7);
|
||||
ux_utility_memory_copy(pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_dpsversions, "1.0 1.1",7);
|
||||
|
||||
pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_vendor_specific_version = 0x0100;
|
||||
|
||||
@@ -78,16 +68,11 @@ if(status != UX_SUCCESS)
|
||||
The parameters passed to the pictbridge client are as follows.
|
||||
|
||||
```C
|
||||
pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_vendor_name
|
||||
: String of Vendor name
|
||||
pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_product_name
|
||||
: String of product name
|
||||
pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_serial_no
|
||||
: String of serial number
|
||||
pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_dpsversions
|
||||
: String of version
|
||||
pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_vendor_specific_version
|
||||
: Value set to 0x0100;
|
||||
pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_vendor_name : String of Vendor name
|
||||
pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_product_name : String of product name
|
||||
pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_serial_no : String of serial number
|
||||
pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_dpsversions : String of version
|
||||
pictbridge.ux_pictbridge_dpslocal.ux_pictbridge_devinfo_vendor_specific_version : Value set to 0x0100;
|
||||
```
|
||||
|
||||
The next step is for the device and the host to synchronize and be ready to exchange information.
|
||||
@@ -97,8 +82,8 @@ This is done by waiting on an event flag as follows.
|
||||
```C
|
||||
/* We should wait for the host and the client to discover one another. */
|
||||
status = ux_utility_event_flags_get(&pictbridge.ux_pictbridge_event_flags_group,
|
||||
UX_PICTBRIDGE_EVENT_FLAG_DISCOVERY,TX_AND_CLEAR,
|
||||
&actual_flags, UX_PICTBRIDGE_EVENT_TIMEOUT);
|
||||
UX_PICTBRIDGE_EVENT_FLAG_DISCOVERY,TX_AND_CLEAR,
|
||||
&actual_flags, UX_PICTBRIDGE_EVENT_TIMEOUT);
|
||||
```
|
||||
|
||||
If the state machine is in the **DISCOVERY_COMPLETE** state, the camera side (the DPS client) will gather information regarding the printer and its capabilities.
|
||||
@@ -107,8 +92,7 @@ If the DPS client is ready to accept a print job, its status will be set to **UX
|
||||
|
||||
```C
|
||||
/* Check if the printer is ready for a print job. */
|
||||
if (pictbridge.ux_pictbridge_dpsclient.ux_pictbridge_devinfo_newjobok ==
|
||||
UX_PICTBRIDGE_NEW_JOB_TRUE)
|
||||
if (pictbridge.ux_pictbridge_dpsclient.ux_pictbridge_devinfo_newjobok == UX_PICTBRIDGE_NEW_JOB_TRUE)
|
||||
/* We can print something … */
|
||||
```
|
||||
|
||||
@@ -122,54 +106,37 @@ jobinfo = &pictbridge.ux_pictbridge_jobinfo;
|
||||
jobinfo -> ux_pictbridge_jobinfo_printinfo_start = &printinfo;
|
||||
|
||||
/* Set the default values for print job. */
|
||||
jobinfo -> ux_pictbridge_jobinfo_quality =
|
||||
UX_PICTBRIDGE_QUALITIES_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_papersize =
|
||||
UX_PICTBRIDGE_PAPER_SIZES_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_papertype =
|
||||
UX_PICTBRIDGE_PAPER_TYPES_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_filetype =
|
||||
UX_PICTBRIDGE_FILE_TYPES_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_dateprint =
|
||||
UX_PICTBRIDGE_DATE_PRINTS_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_filenameprint =
|
||||
UX_PICTBRIDGE_FILE_NAME_PRINTS_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_imageoptimize =
|
||||
UX_PICTBRIDGE_IMAGE_OPTIMIZES_OFF;
|
||||
jobinfo -> ux_pictbridge_jobinfo_layout =
|
||||
UX_PICTBRIDGE_LAYOUTS_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_fixedsize =
|
||||
UX_PICTBRIDGE_FIXED_SIZE_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_cropping =
|
||||
UX_PICTBRIDGE_CROPPINGS_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_quality = UX_PICTBRIDGE_QUALITIES_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_papersize = UX_PICTBRIDGE_PAPER_SIZES_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_papertype = UX_PICTBRIDGE_PAPER_TYPES_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_filetype = UX_PICTBRIDGE_FILE_TYPES_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_dateprint = UX_PICTBRIDGE_DATE_PRINTS_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_filenameprint = UX_PICTBRIDGE_FILE_NAME_PRINTS_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_imageoptimize = UX_PICTBRIDGE_IMAGE_OPTIMIZES_OFF;
|
||||
jobinfo -> ux_pictbridge_jobinfo_layout = UX_PICTBRIDGE_LAYOUTS_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_fixedsize = UX_PICTBRIDGE_FIXED_SIZE_DEFAULT;
|
||||
jobinfo -> ux_pictbridge_jobinfo_cropping = UX_PICTBRIDGE_CROPPINGS_DEFAULT;
|
||||
|
||||
/* Program the callback function for reading the object data. */
|
||||
jobinfo -> ux_pictbridge_jobinfo_object_data_read =
|
||||
ux_demo_object_data_copy;
|
||||
jobinfo -> ux_pictbridge_jobinfo_object_data_read = ux_demo_object_data_copy;
|
||||
|
||||
/* This is a demo, the fileID is hardwired (1 and 2 for scripts, 3 for photo to be printed. */
|
||||
printinfo.ux_pictbridge_printinfo_fileid =
|
||||
UX_PICTBRIDGE_OBJECT_HANDLE_PRINT;
|
||||
ux_utility_memory_copy(printinfo.ux_pictbridge_printinfo_filename,
|
||||
"Pictbridge demo file", 20);
|
||||
ux_utility_memory_copy(printinfo.ux_pictbridge_printinfo_date, "01/01/2008",
|
||||
10);
|
||||
printinfo.ux_pictbridge_printinfo_fileid = UX_PICTBRIDGE_OBJECT_HANDLE_PRINT;
|
||||
ux_utility_memory_copy(printinfo.ux_pictbridge_printinfo_filename, "Pictbridge demo file", 20);
|
||||
ux_utility_memory_copy(printinfo.ux_pictbridge_printinfo_date, "01/01/2008", 10);
|
||||
|
||||
/* Fill in the object info to be printed. First get the pointer to the object container in the job info structure. */
|
||||
object = (UX_SLAVE_CLASS_PIMA_OBJECT *) jobinfo ->
|
||||
ux_pictbridge_jobinfo_object;
|
||||
object = (UX_SLAVE_CLASS_PIMA_OBJECT *) jobinfo -> ux_pictbridge_jobinfo_object;
|
||||
|
||||
/* Store the object format: JPEG picture. */
|
||||
object -> ux_device_class_pima_object_format = UX_DEVICE_CLASS_PIMA_OFC_EXIF_JPEG;
|
||||
object -> ux_device_class_pima_object_compressed_size = IMAGE_LEN;
|
||||
object -> ux_device_class_pima_object_offset = 0;
|
||||
object -> ux_device_class_pima_object_handle_id =
|
||||
UX_PICTBRIDGE_OBJECT_HANDLE_PRINT;
|
||||
object -> ux_device_class_pima_object_handle_id = UX_PICTBRIDGE_OBJECT_HANDLE_PRINT;
|
||||
object -> ux_device_class_pima_object_length = IMAGE_LEN;
|
||||
|
||||
/* File name is in Unicode. */
|
||||
ux_utility_string_to_unicode("JPEG Image", object ->
|
||||
ux_device_class_pima_object_filename);
|
||||
ux_utility_string_to_unicode("JPEG Image", object -> ux_device_class_pima_object_filename);
|
||||
|
||||
/* And start the job. */
|
||||
status =ux_pictbridge_dpsclient_api_start_job(&pictbridge);
|
||||
|
||||
@@ -12,20 +12,20 @@ The regular controller driver functions (host or device) can still be found in t
|
||||
|
||||
There are four categories of functions for an OTG controller in addition to the usual host/device functions.
|
||||
|
||||
- VBUS specific functions
|
||||
- Start and Stop of the controller
|
||||
- USB role manager
|
||||
- Interrupt handlers
|
||||
- [VBUS specific functions](#vbus_specific_functions)
|
||||
- [Start and Stop the controller](#start_and_Stop_the_controller)
|
||||
- [USB role manager](#usb_role_manager)
|
||||
- [Interrupt handlers](#interrupt_handlers)
|
||||
|
||||
## VBUS functions
|
||||
## vbus_specific_functions
|
||||
|
||||
Each controller needs to have a VBUS manager to change the state of VBUS based on power management requirements. Usually, this function only performs turning on or off VBUS.
|
||||
|
||||
## Start and Stop the controller
|
||||
## start_and_Stop_the_controller
|
||||
|
||||
Unlike a regular USB implementation, OTG requires the host and/or the device stack to be activated and deactivated when the role changes.
|
||||
|
||||
## USB role Manager
|
||||
## usb_role_manager
|
||||
|
||||
The USB role manager receives commands to change the state of the USB. There are several states that need transitions to and from:
|
||||
|
||||
@@ -39,7 +39,7 @@ The USB role manager receives commands to change the state of the USB. There are
|
||||
| UX_OTG_SLAVE_TO_IDLE | 5 | Slave device is disconnected |
|
||||
| UX_OTG_SLAVE_TO_HOST | 6 | Role swap from Slave to Host |
|
||||
|
||||
## Interrupt handlers
|
||||
## interrupt_handlers
|
||||
|
||||
Both host and device controller drivers for OTG needs different interrupt handlers to monitor signals beyond traditional USB interrupts, in particular signals due to SRP and VBUS.
|
||||
|
||||
@@ -47,8 +47,7 @@ How to initialize a USB OTG controller. We use the NXP LPC3131 as an example her
|
||||
|
||||
```C
|
||||
/* Initialize the LPC3131 OTG controller. */
|
||||
status = ux_otg_lpc3131_initialize(0x19000000, lpc3131_vbus_function,
|
||||
tx_demo_change_mode_callback);
|
||||
status = ux_otg_lpc3131_initialize(0x19000000, lpc3131_vbus_function, demo_change_mode_callback);
|
||||
```
|
||||
|
||||
In this example, we initialize the LPC3131 in OTG mode by passing a VBUS function and a callback for mode change (from host to slave or vice versa).
|
||||
@@ -56,7 +55,8 @@ In this example, we initialize the LPC3131 in OTG mode by passing a VBUS functio
|
||||
The callback function should simply record the new mode and wake up a pending thread to act up the new state.
|
||||
|
||||
```C
|
||||
void tx_demo_change_mode_callback(ULONG mode) {
|
||||
void demo_change_mode_callback(ULONG mode)
|
||||
{
|
||||
/* Simply save the otg mode. */
|
||||
otg_mode = mode;
|
||||
|
||||
@@ -95,6 +95,5 @@ For a slave device, there is no command to issue but the slave device can set a
|
||||
```C
|
||||
/* We are a B device, ask for role swap.
|
||||
The next GET_STATUS from the host will get the status change and do the HNP. */
|
||||
_ux_system_otg -> ux_system_otg_slave_role_swap_flag =
|
||||
UX_OTG_HOST_REQUEST_FLAG;
|
||||
_ux_system_otg -> ux_system_otg_slave_role_swap_flag = UX_OTG_HOST_REQUEST_FLAG;
|
||||
```
|
||||
|
||||
459
rtos-docs/usbx/usbx-device-stack-supplemental-6.md
Normal file
459
rtos-docs/usbx/usbx-device-stack-supplemental-6.md
Normal file
@@ -0,0 +1,459 @@
|
||||
---
|
||||
title: Chapter 6 - USBX Implement controller driver (DCD)
|
||||
description: This guide is about how to implement device controller driver (DCD) of specific hardware for USBX.
|
||||
---
|
||||
# Chapter 6 - USBX Implement controller driver (DCD)
|
||||
|
||||
# Device Controller Driver (DCD)
|
||||
|
||||
The device controller driver is a driver layer to provide a unique way to access different USB hardware peripherals.
|
||||
|
||||
## DCD for USBX Device Stack
|
||||
|
||||
The USBX device stack accesses device controller through a unique struct of device controller driver (DCD).
|
||||
After USBX system initialization (`ux_system_initialize`), the USBX DCD struct (`UX_SLAVE_DCD`) is allocated and can be referenced by
|
||||
`_ux_system_slave -> ux_system_slave_dcd`.
|
||||
|
||||
## DCD for specific USB controller hardware
|
||||
|
||||
For different USB controller hardware the DCD struct is initialized by specific initialize function, called in application.
|
||||
The actual implements are then linked for USBX device stack to communicate, so that the USB flow can be performed on actual physical device.
|
||||
There are three parts in such a interface:
|
||||
* APIs for application
|
||||
* APIs for USBX stack
|
||||
* USB events (callbacks) to call USBX stack
|
||||
|
||||
### APIs for application
|
||||
|
||||
- [_ux_dcd_xxxxx_initialize](#_ux_dcd_xxxxx_initialize)
|
||||
- [_ux_dcd_xxxx_uninitialize](#_ux_dcd_xxxx_uninitialize)
|
||||
|
||||
#### _ux_dcd_xxxxx_initialize
|
||||
|
||||
The initialize function for specific DCD is called by USBX application, after `ux_system_initialize`, `ux_device_stack_initialize` and `ux_device_stack_class_register`.
|
||||
It allocates necessary resources for the driver.
|
||||
Usually DCD operates directly on hardware, so the initialize function initialize hardware and connect USB.
|
||||
|
||||
Implement example is as following:
|
||||
|
||||
```c
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function initializes the USB device controller of the XXXXX */
|
||||
/* microcontroller in USBX device system. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* dcd_io Driver specific parameter 1 */
|
||||
/* parameter Driver specific parameter 2 */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* Completion Status */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _ux_dcd_xxx_initialize(ULONG dcd_io, ULONG parameter)
|
||||
{
|
||||
|
||||
UX_SLAVE_DCD *dcd;
|
||||
UX_DCD_XXXXX *dcd_xxxxx;
|
||||
|
||||
|
||||
UX_PARAMETER_NOT_USED(dcd_io);
|
||||
|
||||
/* Get the pointer to the DCD. */
|
||||
dcd = &_ux_system_slave -> ux_system_slave_dcd;
|
||||
|
||||
/* The controller initialized here is of XXXXX type. */
|
||||
dcd -> ux_slave_dcd_controller_type = UX_DCD_XXXXX_SLAVE_CONTROLLER;
|
||||
|
||||
/* Allocate memory for this XXXXX DCD instance. */
|
||||
dcd_xxxxx = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_DCD_XXXXX));
|
||||
|
||||
/* Check if memory was properly allocated. */
|
||||
if(dcd_xxxxx == UX_NULL)
|
||||
return(UX_MEMORY_INSUFFICIENT);
|
||||
|
||||
/* Set the pointer to the XXXXX DCD. */
|
||||
dcd -> ux_slave_dcd_controller_hardware = (VOID *) dcd_xxxxx;
|
||||
|
||||
/* Initialize the function collector for this DCD. */
|
||||
dcd -> ux_slave_dcd_function = _ux_dcd_xxxxx_function;
|
||||
|
||||
/* Set the generic DCD owner for the XXXXX DCD. */
|
||||
dcd_xxxxx -> ux_dcd_xxxxx_dcd_owner = dcd;
|
||||
|
||||
/* Initialize XXXXX DCD. */
|
||||
/* TODO: Initialize XXXXX DCD struct fields. */
|
||||
/* TODO: if not initialized in application (after invoking this function),
|
||||
initialize controller hardware and attach to host. */
|
||||
|
||||
/* Set the state of the controller to OPERATIONAL now. */
|
||||
dcd -> ux_slave_dcd_status = UX_DCD_STATUS_OPERATIONAL;
|
||||
|
||||
/* Return successful completion. */
|
||||
return(UX_SUCCESS);
|
||||
}
|
||||
```
|
||||
|
||||
#### _ux_dcd_xxxx_uninitialize (optional)
|
||||
|
||||
The uninitialize function for specific DCD is optional,
|
||||
since the USB device system is usually enabled and always ready to serve.
|
||||
In some cases, it is called by USBX application,
|
||||
if the application needs a way to disconnect USB, completely free resources and uninitialize hardware.
|
||||
Code example is as following:
|
||||
|
||||
```c
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function uninitializes the USB device controller in USBX */
|
||||
/* device system. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* dcd_io Driver specific parameter 1 */
|
||||
/* parameter Driver specific parameter 2 */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* Completion Status */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _ux_dcd_xxxxx_uninitialize(ULONG dcd_io, ULONG parameter)
|
||||
{
|
||||
UX_SLAVE_DCD *dcd;
|
||||
UX_DCD_XXXXX *dcd_xxxxx;
|
||||
UX_PARAMETER_NOT_USED(dcd_io);
|
||||
UX_PARAMETER_NOT_USED(parameter);
|
||||
/* Get the pointer to the DCD. */
|
||||
dcd = &_ux_system_slave -> ux_system_slave_dcd;
|
||||
/* Set the state of the controller to HALTED now. */
|
||||
dcd -> ux_slave_dcd_status = UX_DCD_STATUS_HALTED;
|
||||
/* Get controller driver. */
|
||||
dcd_xxxxx = (UX_DCD_XXXXX *)dcd -> ux_slave_dcd_controller_hardware;
|
||||
/* Free XXXXX driver. */
|
||||
{
|
||||
_ux_utility_memory_free(dcd_xxxxx);
|
||||
dcd -> ux_slave_dcd_controller_hardware = UX_NULL;
|
||||
}
|
||||
/* TODO: If not uninitialized in application (after invoking this function),
|
||||
detach from host and uninitialize the controller. */
|
||||
return(UX_SUCCESS);
|
||||
}
|
||||
```
|
||||
|
||||
### Stack APIs for USBX
|
||||
|
||||
#### ux_dcd_xxxxx_function
|
||||
|
||||
In USBX device stack, the commands sent to controller is in a single API call defined as:
|
||||
|
||||
```c
|
||||
UINT ux_dcd_xxxxx_function(UX_SLAVE_DCD *dcd, UINT cmd, VOID *param);
|
||||
```
|
||||
The commands should be implemented as following:
|
||||
| command | parameter | description |
|
||||
| ------------------------------------------- | ------------------------------- | ------------------------------------------------- |
|
||||
| UX_DCD_TRANSFER_REQUEST/UX_DCD_TRANSFER_RUN | UX_SLAVE_TRANSFER* | Issue a transfer/run transfer state machine |
|
||||
| UX_DCD_TRANSFER_ABORT | UX_SLAVE_TRANSFER* | Abort on going transfer |
|
||||
| UX_DCD_CREATE_ENDPOINT | UX_SLAVE_ENDPOINT* | Create a physical endpoint |
|
||||
| UX_DCD_DESTROY_ENDPOINT | UX_SLAVE_ENDPOINT* | Destroy a physical endpoint |
|
||||
| UX_DCD_RESET_ENDPOINT | UX_SLAVE_ENDPOINT* | Reset an endpoint |
|
||||
| UX_DCD_STALL_ENDPOINT | UX_SLAVE_ENDPOINT* | Stall an endpoint |
|
||||
| UX_DCD_ENDPOINT_STATUS | ULONG | Return status of endpoint (index/address) |
|
||||
| UX_DCD_SET_DEVICE_ADDRESS | ULONG | Set the device address |
|
||||
| UX_DCD_CHANGE_STATE | ULONG (UX_DEVICE_REMOTE_WAKEUP) | Change USB state (to remote wakeup) |
|
||||
| UX_DCD_ISR_PENDING/UX_DCD_TASKS_RUN | - | For standalone, run background task state machine |
|
||||
Note for command `UX_DCD_CHANGE_STATE`, parameter of `UX_DEVICE_REMOTE_WAKEUP` should be accepted and send remote wakeup signal to host.
|
||||
Implement example is as following:
|
||||
```c
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function dispatches the DCD function internally to the XXXXX */
|
||||
/* controller in USBX device system. */
|
||||
/* */
|
||||
/* Following commands are supported: */
|
||||
/* - UX_DCD_TRANSFER_REQUEST/UX_DCD_TRANSFER_RUN */
|
||||
/* - control transfer: mandatory for all devices; */
|
||||
/* - bulk/interrupt/isochronous transfer: optional if needed, e.g., */
|
||||
/* bulk is needed by CDC, Mass Storage classes, */
|
||||
/* interrupt is needed by HID class, */
|
||||
/* isochronous is needed by audio/video classes, etc. */
|
||||
/* - UX_DCD_TRANSFER_ABORT */
|
||||
/* - UX_DCD_CREATE_ENDPOINT */
|
||||
/* - UX_DCD_DESTROY_ENDPOINT */
|
||||
/* - UX_DCD_RESET_ENDPOINT */
|
||||
/* - UX_DCD_ENDPOINT_STATUS */
|
||||
/* - UX_DCD_SET_DEVICE_ADDRESS */
|
||||
/* - UX_DCD_CHANGE_STATE */
|
||||
/* - UX_DEVICE_REMOTE_WAKEUP: optional if remote wakeup is supported */
|
||||
/* - UX_DCD_ISR_PENDING/UX_DCD_TASKS_RUN */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* dcd Pointer to device controller */
|
||||
/* function Function requested */
|
||||
/* parameter Pointer to function parameters*/
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* Completion Status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* USBX Device Stack */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _ux_dcd_xxxxx_function(UX_SLAVE_DCD *dcd, UINT function, VOID *parameter)
|
||||
{
|
||||
UINT status = UX_FUNCTION_NOT_SUPPORTED;
|
||||
UX_DCD_XXXXX *dcd_xxxxx;
|
||||
/* Check the status of the controller. */
|
||||
if (dcd -> ux_slave_dcd_status == UX_UNUSED)
|
||||
{
|
||||
/* Error trap. */
|
||||
_ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_DCD, UX_CONTROLLER_UNKNOWN);
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONTROLLER_UNKNOWN, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
|
||||
return(UX_CONTROLLER_UNKNOWN);
|
||||
}
|
||||
/* Get the pointer to the XXXXX DCD. */
|
||||
dcd_xxxxx = (UX_DCD_XXXXX *) dcd -> ux_slave_dcd_controller_hardware;
|
||||
/* Look at the function and route it. */
|
||||
switch(function)
|
||||
{
|
||||
case UX_DCD_TRANSFER_REQUEST:
|
||||
/* TODO: controller level transfer state machine/transfer request, parameter: UX_SLAVE_TRANSFER *transfer. */
|
||||
/* Transfer types to support:
|
||||
Control: mandatory for all devices;
|
||||
Bulk: optional, for functions that need bulk endpoint (like CDC-ACM, Mass Storage, etc.);
|
||||
Interrupt: optional, for function that need interrupt endpoint (like HID, CDC-ACM, etc.);
|
||||
Isochronous: optional, for function that need Isochronous endpoint (like audio, video, etc.).
|
||||
*/
|
||||
#if defined(UX_DEVICE_STANDALONE)
|
||||
/* Must be non-blocking;
|
||||
in start state: start background transfer and return UX_STATE_NEXT;
|
||||
in pending state: return UX_STATE_WAIT;
|
||||
in done state: confirm transfer fields including completion code are updated and return UX_STATE_NEXT. */
|
||||
/* ...... */
|
||||
#else
|
||||
/* control request: start background transfer for data stage followed by status stage.
|
||||
/* non-control: it's blocking, start background transfer and wait transfer->ux_slave_transfer_request_semaphore. */
|
||||
/* ...... */
|
||||
#endif
|
||||
break;
|
||||
case UX_DCD_TRANSFER_ABORT:
|
||||
/* TODO: controller level transfer abort, parameter: UX_SLAVE_TRANSFER *transfer. */
|
||||
/* ...... */
|
||||
break;
|
||||
case UX_DCD_CREATE_ENDPOINT:
|
||||
/* TODO: controller level endpoint create, parameter: UX_SLAVE_ENDPOINT *endpoint. */
|
||||
/* ...... */
|
||||
break;
|
||||
case UX_DCD_DESTROY_ENDPOINT:
|
||||
/* TODO: controller level endpoint destroy, parameter: UX_SLAVE_ENDPOINT *endpoint. */
|
||||
/* ...... */
|
||||
break;
|
||||
case UX_DCD_RESET_ENDPOINT:
|
||||
/* TODO: controller level endpoint reset to clear halt and reset toggle, parameter: UX_SLAVE_ENDPOINT *endpoint. */
|
||||
/* ...... */
|
||||
break;
|
||||
case UX_DCD_STALL_ENDPOINT:
|
||||
/* TODO: controller level endpoint stall, parameter: UX_SLAVE_ENDPOINT *endpoint. */
|
||||
/* ...... */
|
||||
break;
|
||||
case UX_DCD_SET_DEVICE_ADDRESS:
|
||||
/* TODO: update hardware to set address of the device, parameter: ULONG address. */
|
||||
/* ...... */
|
||||
break;
|
||||
case UX_DCD_CHANGE_STATE:
|
||||
/* TODO: actively change USB state in controller level, parameter: ULONG state. It could be:
|
||||
- UX_DEVICE_REMOTE_WAKEUP: send remote wakeup signal on USB bus (if device needs the feature). */
|
||||
/* ...... */
|
||||
break;
|
||||
case UX_DCD_ENDPOINT_STATUS:
|
||||
/* TODO: get endpoint status (stall).. */
|
||||
/* If UX_DEVICE_BIDIRECTIONAL_ENDPOINT_SUPPORT is defined parameter is ULONG endpoint_address,
|
||||
which kept endpoint direction, in this case both 0x81 and 0x01 are accepted as different
|
||||
endpoints addresses.
|
||||
Otherwise, parameter is ULONG endpoint_index, which removes endpoint direction, in this case
|
||||
address of 0x81 and 0x01 both pass index 0x01 as parameter, so the index must be unique. */
|
||||
/* ...... */
|
||||
break;
|
||||
#if defined(UX_DEVICE_STANDALONE)
|
||||
case UX_DCD_TASKS_RUN:
|
||||
/* TODO: controller level background tasks running. */
|
||||
/* ...... */
|
||||
status = UX_SUCCESS;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* Error trap. */
|
||||
_ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_DCD, status);
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, status, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
|
||||
break;
|
||||
}
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
```
|
||||
|
||||
### Events CALLs to USBX
|
||||
|
||||
Following USBX device stack function should be called in event handling:
|
||||
|
||||
#### ux_device_stack_control_request_process(UX_SLAVE_TRANSFER *)
|
||||
|
||||
* Control SETUP received and IN (device to host) data is expected
|
||||
* Control SETUP received and there is no OUT (host to device) data
|
||||
* Control SETUP received and OUT data also received
|
||||
|
||||
E.g., for a DCD based on STM32 HAL, the code reference could be:
|
||||
|
||||
```c
|
||||
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* ...... */
|
||||
|
||||
/* Check if the transaction is IN. */
|
||||
if (*transfer_request -> ux_slave_transfer_request_setup & UX_REQUEST_IN)
|
||||
{
|
||||
|
||||
/* ...... */
|
||||
|
||||
/* Call the Control Transfer dispatcher. */
|
||||
_ux_device_stack_control_request_process(transfer_request);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ....... */
|
||||
|
||||
/* We are in a OUT transaction. Check if there is a data payload. If so, wait for the payload
|
||||
to be delivered. */
|
||||
if (*(transfer_request -> ux_slave_transfer_request_setup + 6) == 0 &&
|
||||
*(transfer_request -> ux_slave_transfer_request_setup + 7) == 0)
|
||||
{
|
||||
|
||||
/* Call the Control Transfer dispatcher. */
|
||||
_ux_device_stack_control_request_process(transfer_request);
|
||||
|
||||
/* TODO: start background control request status phase. */
|
||||
/* ...... */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO: start background control request data OUT transfer,
|
||||
when transfer/partial transfer is done, HAL_PCD_DataOutStageCallback is triggered. */
|
||||
/* ...... */
|
||||
}
|
||||
}
|
||||
}
|
||||
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||
{
|
||||
/* Endpoint 0 is the control endpoint. */
|
||||
if (epnum == 0U)
|
||||
{
|
||||
/* Check if we have received something on control endpoint during data phase . */
|
||||
if (ed -> ux_dcd_stm32_ed_state == UX_DCD_STM32_ED_STATE_DATA_RX)
|
||||
{
|
||||
/* Are we done with this transfer ? */
|
||||
if ((transfer_request -> ux_slave_transfer_request_actual_length ==
|
||||
transfer_request -> ux_slave_transfer_request_requested_length) ||
|
||||
(transfer_length != endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize))
|
||||
{
|
||||
/* ...... */
|
||||
|
||||
_ux_device_stack_control_request_process(transfer_request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
#### ux_device_stack_disconnect(void)
|
||||
|
||||
* A USB bus reset happen in not reset states.
|
||||
* A USB bus disconnect happen in not reset states
|
||||
E.g., for a DCD based on STM32 HAL, the code reference could be:
|
||||
```c
|
||||
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* If the device is attached or configured, we need to disconnect it. */
|
||||
if (_ux_system_slave -> ux_system_slave_device.ux_slave_device_state != UX_DEVICE_RESET)
|
||||
{
|
||||
/* Disconnect the device. */
|
||||
_ux_device_stack_disconnect();
|
||||
}
|
||||
/* Put the device in attached default state. */
|
||||
/* ...... */
|
||||
}
|
||||
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Check if the device is attached or configured. */
|
||||
if (_ux_system_slave -> ux_system_slave_device.ux_slave_device_state != UX_DEVICE_RESET)
|
||||
{
|
||||
/* Disconnect the device. */
|
||||
_ux_device_stack_disconnect();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### _ux_system_slave -> ux_system_slave_speed and _ux_system_slave -> ux_system_slave_device.ux_slave_device_state
|
||||
|
||||
* Updated when USB bus reset is done
|
||||
|
||||
E.g., for a DCD based on STM32 HAL, the code reference could be:
|
||||
```c
|
||||
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
|
||||
/* ...... */
|
||||
|
||||
/* Set USB Current Speed */
|
||||
switch(hpcd -> Init.speed)
|
||||
{
|
||||
case PCD_SPEED_HIGH:
|
||||
|
||||
/* We are connected at high speed. */
|
||||
_ux_system_slave -> ux_system_slave_speed = UX_HIGH_SPEED_DEVICE;
|
||||
break;
|
||||
|
||||
case PCD_SPEED_FULL:
|
||||
|
||||
/* We are connected at full speed. */
|
||||
_ux_system_slave -> ux_system_slave_speed = UX_FULL_SPEED_DEVICE;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* We are connected at full speed. */
|
||||
_ux_system_slave -> ux_system_slave_speed = UX_FULL_SPEED_DEVICE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* ...... */
|
||||
|
||||
/* Mark the device as attached now. */
|
||||
_ux_system_slave -> ux_system_slave_device.ux_slave_device_state = UX_DEVICE_ATTACHED;
|
||||
}
|
||||
```
|
||||
303
rtos-docs/usbx/usbx-device-stack-supplemental-7.md
Normal file
303
rtos-docs/usbx/usbx-device-stack-supplemental-7.md
Normal file
@@ -0,0 +1,303 @@
|
||||
---
|
||||
title: Chapter 6 - USBX Implement device class modules
|
||||
description: This guide is about how to implement device class modules for specific device classes/functions in USBX.
|
||||
---
|
||||
# Chapter 6 - USBX Implement device class modules
|
||||
|
||||
# Device Class Layer (ux_device_class)
|
||||
|
||||
The device class layer is the class layer above device stack layer.
|
||||
It provides a unique way for different classes/functions to communicate with USBX device stack,
|
||||
and provides class/function specific APIs for the application usages.
|
||||
|
||||
## USBX Device Class
|
||||
|
||||
The USBX device stack accesses device class/function modules through a unique struct of `UX_SLAVE_CLASS`.
|
||||
It's the container for specific (local) class modules. It's allocated on USBX device stack initialization, and can be referenced as `_ux_system_slave -> ux_system_slave_class_array`.
|
||||
|
||||
## USBX Device Class Module for specific class/function
|
||||
|
||||
For different USB class/function the device class struct is linked to specific class entry function, called by USBX device stack.
|
||||
The actual implements then handles the commands from USBX device stack, to:
|
||||
* initialize/uninitialize the class/function;
|
||||
* query if the class/function is supported;
|
||||
* activate/deactivate the class/function;
|
||||
* process class specific requests received;
|
||||
* handle the interface alternate setting change.
|
||||
|
||||
The device class module may also provide application APIs and/or callbacks to perform class specific data/control exchange with application.
|
||||
|
||||
### USBX Device Class Entry for Device Stack
|
||||
|
||||
The device class/function module must provide an entry function. It's a parameter for `ux_device_stack_class_register` to register the class module on device stack and do initialization. It dispatches commands from USBX device stack for standard and class specific host requests handling.
|
||||
|
||||
The prototype for the function is:
|
||||
```c
|
||||
UINT _ux_device_class_xxxxx_entry(UX_SLAVE_CLASS_COMMAND *command);
|
||||
```
|
||||
The command data is encapsulated in a struct of `UX_SLAVE_CLASS_COMMAND`, where `ux_slave_class_command_request` holds the device stack command to process and others are parameters for the command, the possible commands are:
|
||||
| request | _interface | _class/_subclass/_protocol | _class_ptr | _parameter | Description |
|
||||
| ---------------------------------------------- | --------------------- | -------------------------- | ----------------- | ------------ | ----------------------------------------------------------- |
|
||||
| UX_SLAVE_CLASS_COMMAND_INITIALIZE | not used | not used | (UX_SLAVE_CLASS*) | (VOID*)param | Initialize class/function module instance |
|
||||
| UX_SLAVE_CLASS_COMMAND_QUERY | (UX_SLAVE_INTERFACE*) | ULONG | (UX_SLAVE_CLASS*) | not used | Query if class/subclass/protocol is supported |
|
||||
| UX_SLAVE_CLASS_COMMAND_ACTIVATE | (UX_SLAVE_INTERFACE*) | ULONG | (UX_SLAVE_CLASS*) | not used | Activate local class/function instance |
|
||||
| UX_SLAVE_CLASS_COMMAND_DEACTIVATE | (UX_SLAVE_INTERFACE*) | not used | not used | not used | Deactivate notification |
|
||||
| UX_SLAVE_CLASS_COMMAND_REQUEST (optional) | not used | not used | (UX_SLAVE_CLASS*) | not used | Handle class/vendor requests from host (if needed) |
|
||||
| UX_SLAVE_CLASS_COMMAND_CHANGE (optional) | (UX_SLAVE_INTERFACE*) | not used | (UX_SLAVE_CLASS*) | not used | Interface alternate setting change notification (if needed) |
|
||||
| UX_SLAVE_CLASS_COMMAND_UNINITIALIZE (optional) | not used | not used | (UX_SLAVE_CLASS*) | not used | Uninitialize class/function module instance |
|
||||
|
||||
The function entry implement example is as following:
|
||||
|
||||
```c
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is the entry point of the xxxxx class. It */
|
||||
/* will be called by the device stack when the host has sent specific */
|
||||
/* request and the xxxxx class/function needs to be processed. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* command Pointer to class command */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* Completion Status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* USBX Device Stack */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _ux_device_class_xxxxx_entry(UX_SLAVE_CLASS_COMMAND *command)
|
||||
{
|
||||
UINT status;
|
||||
/* The command request will tell us we need to do here, either a enumeration
|
||||
query, an activation or a deactivation, etc. */
|
||||
switch (command -> ux_slave_class_command_request)
|
||||
{
|
||||
case UX_SLAVE_CLASS_COMMAND_INITIALIZE:
|
||||
/* TODO: Initialize the device class/function instance. */
|
||||
/* Allocates instance memory and other related resources and initialize them. */
|
||||
/* Link the instance to container so it can be referenced. */
|
||||
/* ...... */
|
||||
return(status);
|
||||
case UX_SLAVE_CLASS_COMMAND_UNINITIALIZE:
|
||||
/* TODO: uninitialize the device class/function instance. */
|
||||
/* Uninitialize, free the resources and release instance memory. */
|
||||
/* ...... */
|
||||
return(status);
|
||||
case UX_SLAVE_CLASS_COMMAND_QUERY:
|
||||
/* TODO: check class and/or subclass and/or protocol to see if it's supported. */
|
||||
if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_XXXXX_CLASS)
|
||||
return(UX_SUCCESS);
|
||||
else
|
||||
return(UX_NO_CLASS_MATCH);
|
||||
case UX_SLAVE_CLASS_COMMAND_ACTIVATE:
|
||||
/* TODO: activate the device class/function instance. */
|
||||
/* The activate command is used when the host has sent a SET_CONFIGURATION command and this interface has to be mounted. */
|
||||
/* Mandatory endpoints have to be mounted and the class thread needs to be activated if needed. */
|
||||
/* If instance activation is success and there is notification callback, notify application. */
|
||||
/* ...... */
|
||||
return(status);
|
||||
case UX_SLAVE_CLASS_COMMAND_CHANGE:
|
||||
/* TODO: notify that the interface alternate setting has been changed (optional). */
|
||||
/* The change command is used when the host has sent a SET_INTERFACE command
|
||||
to go from Alternate Setting 0 to >0 or revert to the default mode (0). */
|
||||
/* ...... */
|
||||
return(status);
|
||||
case UX_SLAVE_CLASS_COMMAND_DEACTIVATE:
|
||||
/* TODO: deactivate the device class/function instance (optional). */
|
||||
/* The deactivate command is used when the device has been extracted. */
|
||||
/* The instance endpoints have to be dismounted and the class thread canceled. */
|
||||
/* If there is notification callback, notify application. */
|
||||
/* ...... */
|
||||
return(status);
|
||||
case UX_SLAVE_CLASS_COMMAND_REQUEST:
|
||||
/* TODO: handle host class/vendor requests (optional). */
|
||||
/* The request command is used when the host sends a command on the control endpoint. */
|
||||
/* ...... */
|
||||
return(status);
|
||||
default:
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
|
||||
/* Return an error. */
|
||||
return(UX_FUNCTION_NOT_SUPPORTED);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### UX_SLAVE_CLASS_COMMAND_INITIALIZE
|
||||
|
||||
The initialize command implement example is as following:
|
||||
|
||||
```c
|
||||
/* ...... */
|
||||
|
||||
/* Get the pointer to the application parameters for the xxxxx class. */
|
||||
xxxxx_parameter = command -> ux_slave_class_command_parameter;
|
||||
|
||||
/* Get the class container. */
|
||||
class_ptr = command -> ux_slave_class_command_class_ptr;
|
||||
|
||||
/* Create an instance of the device xxxxx class. */
|
||||
xxxxx = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_xxxxx));
|
||||
|
||||
/* Check for successful allocation. */
|
||||
if (xxxxx == UX_NULL)
|
||||
return(UX_MEMORY_INSUFFICIENT);
|
||||
|
||||
/* Save the address of the xxxxx instance inside the container. */
|
||||
class_ptr -> ux_slave_class_instance = (VOID *) xxxxx;
|
||||
|
||||
/* TODO: class/function specific initialization. */
|
||||
/* ...... */
|
||||
```
|
||||
|
||||
#### UX_SLAVE_CLASS_COMMAND_QUERY
|
||||
|
||||
The query command implement example is as following:
|
||||
|
||||
```c
|
||||
if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_XXXXX_CLASS &&
|
||||
command -> ux_slave_class_command_subclass == UX_DEVICE_CLASS_XXXXX_SUBCLASS &&
|
||||
command -> ux_slave_class_command_protocol == UX_DEVICE_CLASS_XXXXX_PROTOCOL)
|
||||
return(UX_SUCCESS);
|
||||
else
|
||||
return(UX_NO_CLASS_MATCH);
|
||||
```
|
||||
|
||||
#### UX_SLAVE_CLASS_COMMAND_ACTIVATE
|
||||
|
||||
The activate command implement example is as following:
|
||||
|
||||
```c
|
||||
/* ...... */
|
||||
|
||||
/* Get the class container. */
|
||||
class_ptr = command -> ux_slave_class_command_class_ptr;
|
||||
|
||||
/* Get the class instance in the container. */
|
||||
xxxxx = (UX_SLAVE_CLASS_xxxxx *) class_ptr -> ux_slave_class_instance;
|
||||
|
||||
/* Get the interface that owns this instance. */
|
||||
interface_ptr = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface;
|
||||
|
||||
/* Store the class instance into the interface. */
|
||||
interface_ptr -> ux_slave_interface_class_instance = (VOID *)xxxxx;
|
||||
|
||||
/* Now the opposite, store the interface in the class instance. */
|
||||
xxxxx -> ux_slave_class_xxxxx_interface = interface_ptr;
|
||||
|
||||
/* TODO: class/function specific activations, such as:
|
||||
* - Activate class and function specific threads.
|
||||
* - Activate function specific endpoints.
|
||||
* - Other class/function specific preparations, etc.
|
||||
*/
|
||||
/* ...... */
|
||||
```
|
||||
|
||||
#### UX_SLAVE_CLASS_COMMAND_DEACTIVATE
|
||||
|
||||
The deactivate command implement example is as following:
|
||||
|
||||
```c
|
||||
UINT _ux_device_class_xxxxx_deactivate(UX_SLAVE_CLASS_COMMAND *command)
|
||||
{
|
||||
/* ...... */
|
||||
|
||||
/* Get the class container. */
|
||||
class_ptr = command -> ux_slave_class_command_class_ptr;
|
||||
|
||||
/* Get the class instance in the container. */
|
||||
xxxxx = (UX_DEVICE_CLASS_XXXXXX *) class_ptr -> ux_slave_class_instance;
|
||||
|
||||
/* TODO: class/function specific deactivations, such as:
|
||||
* - Cancel pending transfers;
|
||||
* - Notify application;
|
||||
* - etc.
|
||||
*/
|
||||
/* ...... */
|
||||
}
|
||||
```
|
||||
#### UX_SLAVE_CLASS_COMMAND_REQUEST
|
||||
|
||||
The request command is optional.
|
||||
It is implemented if the class/function needs to process class/vendor requests from host,
|
||||
implement example is as following:
|
||||
|
||||
```c
|
||||
/* ...... */
|
||||
/* Get the pointer to the device. */
|
||||
device = &_ux_system_slave -> ux_system_slave_device;
|
||||
/* Get the pointer to the transfer request associated with the control endpoint. */
|
||||
transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request;
|
||||
/* Get the class container. */
|
||||
class_ptr = command -> ux_slave_class_command_class_ptr;
|
||||
|
||||
/* Get the storage instance from this class container. */
|
||||
xxxxx = (UX_DEVICE_CLASS_XXXXX *) class_ptr -> ux_slave_class_instance;
|
||||
/* TODO: handle setup request from host. */
|
||||
/* ...... */
|
||||
```
|
||||
|
||||
#### UX_SLAVE_CLASS_COMMAND_CHANGE
|
||||
|
||||
The change command is optional.
|
||||
It is implemented if the class/function needs different interface alternate settings.
|
||||
implement example is as following:
|
||||
|
||||
```c
|
||||
/* ...... */
|
||||
|
||||
/* Get the class container. */
|
||||
class_ptr = command -> ux_slave_class_command_class_ptr;
|
||||
|
||||
/* Get the class instance in the container. */
|
||||
xxxxx = (UX_SLAVE_CLASS_XXXXX *) class_ptr -> ux_slave_class_instance;
|
||||
|
||||
/* Get the interface that owns this instance. */
|
||||
interface_ptr = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface;
|
||||
|
||||
/* Check alternate settings. */
|
||||
if (interface_ptr -> ux_slave_interface_descriptor.bAlternateSetting != 0)
|
||||
{
|
||||
/* TODO: non-zero alternate setting. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO: zero alternate setting. */
|
||||
}
|
||||
|
||||
/* ...... */
|
||||
```
|
||||
#### UX_SLAVE_CLASS_COMMAND_UNINITIALIZE
|
||||
|
||||
The uninitialize command is optional.
|
||||
It is implemented in purpose to free all resources for the class/function support.
|
||||
implement example is as following:
|
||||
|
||||
```c
|
||||
/* ...... */
|
||||
/* Get the class container. */
|
||||
class_ptr = command -> ux_slave_class_command_class_ptr;
|
||||
/* Get the class instance in the container. */
|
||||
hid = (UX_SLAVE_CLASS_HID *) class_ptr -> ux_slave_class_instance;
|
||||
/* TODO: Free resources, like
|
||||
* - Delete threads, semaphores, mutexes, etc.
|
||||
* - Free memories allocated for instance and the instnace memory;
|
||||
* - etc.
|
||||
*/
|
||||
/* ...... */
|
||||
```
|
||||
|
||||
## Other considerations
|
||||
|
||||
### Memory management
|
||||
|
||||
To avoid memory fragmentation, it's recommended to allocate as much as memories in initialize instead of in activation.
|
||||
|
||||
Also if the system does not need USB system deinitialization, it's not necessary to process the command of uninitialize.
|
||||
Reference in New Issue
Block a user