1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
/***************************************************************************
* Copyright (c) 2024 Microsoft Corporation
* Copyright (c) 2026-present Eclipse ThreadX contributors
*
* This program and the accompanying materials are made available under the
* terms of the MIT License which is available at
* https://opensource.org/licenses/MIT.
*
* SPDX-License-Identifier: MIT
**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** USBX Component */
/** */
/** Host Stack */
/** */
/**************************************************************************/
/**************************************************************************/
/* Include necessary system files. */
#define UX_SOURCE_CODE
#include "ux_api.h"
#include "ux_host_stack.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _ux_host_stack_new_interface_create PORTABLE C */
/* 6.1.12 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function creates a new interface for the current configuration */
/* scanned. A device has at least 1 alternate setting per interface */
/* which is the default one. */
/* */
/* The interface is hooked to the configuration that owns it. */
/* */
/* From the interface descriptor, all the endpoints are hooked but */
/* not activated. */
/* */
/* INPUT */
/* */
/* configuration Configuration container that */
/* owns this interface */
/* interface_pointer Pointer to a unparsed */
/* interface descriptor */
/* length Length remaining in this */
/* descriptor */
/* */
/* OUTPUT */
/* */
/* Completion Status */
/* */
/* CALLS */
/* */
/* _ux_host_stack_new_endpoint_create Create new endpoint */
/* _ux_utility_descriptor_parse Parse the descriptor */
/* _ux_utility_memory_allocate Allocate memory block */
/* */
/* CALLED BY */
/* */
/* USBX Components */
/* */
/**************************************************************************/
UINT _ux_host_stack_new_interface_create(UX_CONFIGURATION *configuration,
UCHAR * descriptor, ULONG length)
{
UX_INTERFACE *list_interface;
UX_INTERFACE *interface_ptr;
UINT number_endpoints;
UINT descriptor_length;
UINT descriptor_type;
UINT status;
UCHAR *this_interface_descriptor;
/* Obtain memory for storing this new interface. */
interface_ptr = (UX_INTERFACE *) _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_INTERFACE));
/* If no memory left, exit with error. */
if (interface_ptr == UX_NULL)
return(UX_MEMORY_INSUFFICIENT);
/* Save the interface handle in the container, this is for ensuring the
interface container is not corrupted. */
interface_ptr -> ux_interface_handle = (ULONG) (ALIGN_TYPE) interface_ptr;
/* Parse the interface descriptor and make it machine independent. */
_ux_utility_descriptor_parse(descriptor,
_ux_system_interface_descriptor_structure,
UX_INTERFACE_DESCRIPTOR_ENTRIES,
(UCHAR *) &interface_ptr -> ux_interface_descriptor);
/* The configuration that owns this interface is memorized in the
interface container itself, easier for back chaining. */
interface_ptr -> ux_interface_configuration = configuration;
/* If the interface belongs to an IAD, remember the IAD Class/SubClass/Protocol. */
interface_ptr -> ux_interface_iad_class = configuration -> ux_configuration_iad_class;
interface_ptr -> ux_interface_iad_subclass = configuration -> ux_configuration_iad_subclass;
interface_ptr -> ux_interface_iad_protocol = configuration -> ux_configuration_iad_protocol;
/* There is 2 cases for the creation of the interface descriptor
if this is the first one, the interface descriptor is hooked
to the configuration. If it is not the first one, the interface
is hooked to the end of the chain of interfaces. */
if (configuration -> ux_configuration_first_interface == UX_NULL)
{
configuration -> ux_configuration_first_interface = interface_ptr;
}
else
{
list_interface = configuration -> ux_configuration_first_interface;
/* Traverse the list until we reach the end */
while (list_interface -> ux_interface_next_interface != UX_NULL)
{
list_interface = list_interface -> ux_interface_next_interface;
}
/* Hook the interface. */
list_interface -> ux_interface_next_interface = interface_ptr;
}
/* Traverse the interface in search of all endpoints that belong to it.
We need the length remaining in the descriptor and the number of endpoints
reported for this interface. */
number_endpoints = interface_ptr -> ux_interface_descriptor.bNumEndpoints;
this_interface_descriptor = descriptor;
while (length && (number_endpoints != 0))
{
/* Gather the length and type of the descriptor. */
descriptor_length = *descriptor;
descriptor_type = *(descriptor+1);
/* make sure this descriptor has at least the minimum length. */
if (descriptor_length < 3)
{
/* Error trap. */
_ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED);
/* If trace is enabled, insert this event into the trace buffer. */
UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
return(UX_DESCRIPTOR_CORRUPTED);
}
/* Check the type for an interface descriptor. */
if (descriptor_type == UX_ENDPOINT_DESCRIPTOR_ITEM)
{
/* We have found an endpoint descriptor for this interface. */
status = _ux_host_stack_new_endpoint_create(interface_ptr, descriptor);
/* Check return status. */
if(status != UX_SUCCESS)
return(status);
number_endpoints--;
}
/* Verify if the descriptor is still valid, or we moved to next interface. */
if ((descriptor_length > length) || (descriptor_type == UX_INTERFACE_DESCRIPTOR_ITEM && descriptor != this_interface_descriptor))
{
/* Error trap. */
_ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED);
/* If trace is enabled, insert this event into the trace buffer. */
UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
return(UX_DESCRIPTOR_CORRUPTED);
}
/* Jump to the next descriptor if we have not reached the end. */
descriptor += descriptor_length;
length -= descriptor_length;
}
/* Return success! */
return(UX_SUCCESS);
}
|