1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** USBX Component */
16 /** */
17 /** Device Pima Class */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define UX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "ux_api.h"
28 #include "ux_device_class_pima.h"
29 #include "ux_device_stack.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _ux_device_class_pima_object_prop_value_get PORTABLE C */
37 /* 6.3.0 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* Return an Object Property Value. The value is fetched by calling the */
45 /* application which initialized a call back pointer. The application */
46 /* will copy the value at the specified address. The length of the */
47 /* value of the object will be returned to compute the length of the */
48 /* payload packet. */
49 /* */
50 /* INPUT */
51 /* */
52 /* pima Pointer to pima class */
53 /* object_handle Object Handle */
54 /* object_property_code Object Property code for */
55 /* which the value is obtained. */
56 /* */
57 /* OUTPUT */
58 /* */
59 /* Completion Status */
60 /* */
61 /* CALLS */
62 /* */
63 /* _ux_device_stack_transfer_request Transfer request */
64 /* _ux_utility_long_put Put 32-bit value */
65 /* _ux_utility_short_put Put 32-bit value */
66 /* _ux_utility_memory_copy Copy memory */
67 /* _ux_device_class_pima_response_send Send PIMA response */
68 /* */
69 /* CALLED BY */
70 /* */
71 /* Device Pima Class */
72 /* */
73 /* RELEASE HISTORY */
74 /* */
75 /* DATE NAME DESCRIPTION */
76 /* */
77 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
78 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
79 /* verified memset and memcpy */
80 /* cases, */
81 /* resulting in version 6.1 */
82 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
83 /* updated status handling, */
84 /* passed max length to app, */
85 /* resulting in version 6.1.10 */
86 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), */
87 /* added a new mode to manage */
88 /* endpoint buffer in classes, */
89 /* resulting in version 6.3.0 */
90 /* */
91 /**************************************************************************/
_ux_device_class_pima_object_prop_value_get(UX_SLAVE_CLASS_PIMA * pima,ULONG object_handle,ULONG object_property_code)92 UINT _ux_device_class_pima_object_prop_value_get(UX_SLAVE_CLASS_PIMA *pima,
93 ULONG object_handle,
94 ULONG object_property_code)
95 {
96
97 UINT status;
98 UX_SLAVE_TRANSFER *transfer_request;
99 UCHAR *pima_data_buffer;
100 UCHAR *pima_data_buffer_end;
101 UCHAR *object_property_value;
102 ULONG object_property_value_length;
103
104 /* If trace is enabled, insert this event into the trace buffer. */
105 UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_GET_OBJECT_PROP_VALUE, pima, object_handle, object_property_code, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
106
107 /* Obtain the pointer to the transfer request. */
108 transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request;
109
110 /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */
111 pima_data_buffer = transfer_request -> ux_slave_transfer_request_data_pointer;
112
113 /* Save the end of the buffer. */
114 pima_data_buffer_end = pima_data_buffer + UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH;
115
116 /* Fill in the data container type. */
117 _ux_utility_short_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE,
118 UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK);
119
120 /* Fill in the data code. */
121 _ux_utility_short_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE,
122 UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_PROP_VALUE);
123
124 /* Fill in the Transaction ID. */
125 _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID,
126 pima -> ux_device_class_pima_transaction_id);
127
128 /* Ask the application to retrieve for us the object prop value. */
129 object_property_value_length = UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD;
130 status = pima -> ux_device_class_pima_object_prop_value_get(pima, object_handle, object_property_code, &object_property_value, &object_property_value_length);
131
132 /* Result should always be OK, but to be sure .... */
133 if (status != UX_SUCCESS)
134
135 /* We return an error. */
136 _ux_device_class_pima_response_send(pima, status, 0, 0, 0, 0);
137
138 else
139 {
140
141 /* Check if the prop value will fit. */
142 if (pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + object_property_value_length <= pima_data_buffer_end)
143 {
144
145 /* Copy the property dataset into the local buffer. */
146 _ux_utility_memory_copy(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, object_property_value, object_property_value_length); /* Use case of memcpy is verified. */
147
148 /* Add the header size to the payload. */
149 object_property_value_length += UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE;
150
151 /* Fill in the size of the response header. */
152 _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH,
153 object_property_value_length);
154
155 /* Send a data payload with the object props array. */
156 status = _ux_device_stack_transfer_request(transfer_request, object_property_value_length, 0);
157
158 /* Now we return a response with success. */
159 _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0);
160 }
161 else
162 {
163
164 /* The prop value doesn't fit. */
165
166 /* Report the error to the application. */
167 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT);
168
169 /* Return response code to host. */
170 _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_GENERAL_ERROR, 0, 0, 0, 0);
171
172 /* Return error. */
173 status = UX_MEMORY_INSUFFICIENT;
174 }
175 }
176
177 /* Return completion status. */
178 return(status);
179 }
180
181
182