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_info_get PORTABLE C */
37 /* 6.3.0 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function returns the object info structure to the host. */
45 /* */
46 /* INPUT */
47 /* */
48 /* pima Pointer to pima class */
49 /* */
50 /* OUTPUT */
51 /* */
52 /* Completion Status */
53 /* */
54 /* CALLS */
55 /* */
56 /* _ux_device_stack_transfer_request Transfer request */
57 /* _ux_utility_long_put Put 32-bit value */
58 /* _ux_utility_short_put Put 32-bit value */
59 /* _ux_utility_memory_copy Copy memory */
60 /* _ux_utility_descriptor_pack Pack descriptor */
61 /* _ux_device_class_pima_response_send Send PIMA response */
62 /* */
63 /* CALLED BY */
64 /* */
65 /* Device Storage Class */
66 /* */
67 /* RELEASE HISTORY */
68 /* */
69 /* DATE NAME DESCRIPTION */
70 /* */
71 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
72 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
73 /* verified memset and memcpy */
74 /* cases, */
75 /* resulting in version 6.1 */
76 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
77 /* updated status handling, */
78 /* resulting in version 6.1.10 */
79 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
80 /* internal clean up, */
81 /* resulting in version 6.1.11 */
82 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), */
83 /* added a new mode to manage */
84 /* endpoint buffer in classes, */
85 /* resulting in version 6.3.0 */
86 /* */
87 /**************************************************************************/
_ux_device_class_pima_object_info_get(UX_SLAVE_CLASS_PIMA * pima,ULONG object_handle)88 UINT _ux_device_class_pima_object_info_get(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle)
89 {
90
91 UINT status;
92 UX_SLAVE_TRANSFER *transfer_request;
93 UX_SLAVE_CLASS_PIMA_OBJECT *object;
94 ULONG object_info_length;
95 UCHAR *object_info;
96 UCHAR *object_info_pointer;
97 ULONG file_name_length;
98 ULONG capture_date_length;
99 ULONG modification_date_length;
100 ULONG keywords_length;
101
102
103 /* If trace is enabled, insert this event into the trace buffer. */
104 UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_INFO_GET, pima, object_handle, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
105
106 /* Obtain the object info from the application. */
107 status = pima -> ux_device_class_pima_object_info_get(pima, object_handle, &object);
108
109 /* Check for error. */
110 if (status != UX_SUCCESS)
111
112 /* We return an error. */
113 _ux_device_class_pima_response_send(pima, status, 0, 0, 0, 0);
114
115 else
116 {
117
118 /* Length calculation and overflow check. */
119 file_name_length = ((ULONG) *object -> ux_device_class_pima_object_filename * 2 ) + 1;
120 capture_date_length = ((ULONG) *object -> ux_device_class_pima_object_capture_date *2 ) + 1;
121 modification_date_length = ((ULONG) *object -> ux_device_class_pima_object_modification_date * 2 ) + 1;
122 keywords_length = ((ULONG) *object -> ux_device_class_pima_object_keywords * 2 ) +1;
123 object_info_length = UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE +
124 UX_DEVICE_CLASS_PIMA_OBJECT_VARIABLE_OFFSET +
125 file_name_length +
126 capture_date_length +
127 modification_date_length +
128 keywords_length;
129
130 /* Ensure the object info data can fit in the endpoint's data buffer. */
131 if (object_info_length > UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH)
132 {
133
134 /* If trace is enabled, insert this event into the trace buffer. */
135 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
136
137 /* We return an error. */
138 _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_GENERAL_ERROR, 0, 0, 0, 0);
139
140 /* Return overflow error. */
141 return(UX_MEMORY_INSUFFICIENT);
142 }
143
144 /* Obtain the pointer to the transfer request. */
145 transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request;
146
147 /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */
148 object_info = transfer_request -> ux_slave_transfer_request_data_pointer;
149
150 /* Fill in the data container type. */
151 _ux_utility_short_put(object_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE,
152 UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK);
153
154 /* Fill in the data code. */
155 _ux_utility_short_put(object_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE,
156 UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_INFO);
157
158 /* Fill in the Transaction ID. */
159 _ux_utility_long_put(object_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID,
160 pima -> ux_device_class_pima_transaction_id);
161
162 /* Allocate the device info pointer to the beginning of the dynamic object info field. */
163 object_info_pointer = object_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE;
164
165 /* The object info structure coming from the application needs to be packed. */
166 _ux_utility_descriptor_pack((UCHAR *) object,
167 _ux_system_class_pima_object_structure,
168 UX_DEVICE_CLASS_PIMA_OBJECT_ENTRIES,
169 object_info_pointer);
170
171 /* Copy the object filename field. Point to the beginning of the object description string. */
172 object_info_pointer += UX_DEVICE_CLASS_PIMA_OBJECT_VARIABLE_OFFSET;
173
174 /* Copy that string into the object description field. */
175 _ux_utility_memory_copy(object_info_pointer, object -> ux_device_class_pima_object_filename, file_name_length); /* Use case of memcpy is verified. */
176
177 /* Point to the next field. */
178 object_info_pointer += file_name_length;
179
180 /* Copy that string into the capture date field. */
181 _ux_utility_memory_copy(object_info_pointer, object -> ux_device_class_pima_object_capture_date, capture_date_length); /* Use case of memcpy is verified. */
182
183 /* Point to the next field. */
184 object_info_pointer += capture_date_length;
185
186 /* Copy that string into the modification date field. */
187 _ux_utility_memory_copy(object_info_pointer, object -> ux_device_class_pima_object_modification_date, modification_date_length); /* Use case of memcpy is verified. */
188
189 /* Point to the next field. */
190 object_info_pointer += modification_date_length;
191
192 /* Copy that string into the keywords field. */
193 _ux_utility_memory_copy(object_info_pointer, object -> ux_device_class_pima_object_keywords, keywords_length); /* Use case of memcpy is verified. */
194
195 /* Fill in the size of the response header. */
196 _ux_utility_long_put(object_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH,
197 object_info_length);
198
199 /* Send a data payload with the object info data set. */
200 status = _ux_device_stack_transfer_request(transfer_request, object_info_length, 0);
201
202 /* Now we return a response with success. */
203 _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0);
204 }
205
206 /* Return completion status. */
207 return(status);
208 }
209