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 /** Generic Serial Host module class */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22
23 /* Include necessary system files. */
24
25 #define UX_SOURCE_CODE
26
27 #include "ux_api.h"
28 #include "ux_host_class_gser.h"
29 #include "ux_host_stack.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _ux_host_class_gser_reception_callback PORTABLE C */
37 /* 6.1 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function is the callback from the USBX transfer functions, */
45 /* it is called when a full or partial transfer has been done for a */
46 /* bulk in transfer. It calls back the application. */
47 /* */
48 /* INPUT */
49 /* */
50 /* transfer_request Pointer to transfer request */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* None */
55 /* */
56 /* CALLS */
57 /* */
58 /* _ux_host_stack_transfer_request Process transfer request */
59 /* */
60 /* CALLED BY */
61 /* */
62 /* Application */
63 /* */
64 /* RELEASE HISTORY */
65 /* */
66 /* DATE NAME DESCRIPTION */
67 /* */
68 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
69 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
70 /* resulting in version 6.1 */
71 /* */
72 /**************************************************************************/
_ux_host_class_gser_reception_callback(UX_TRANSFER * transfer_request)73 VOID _ux_host_class_gser_reception_callback (UX_TRANSFER *transfer_request)
74 {
75
76 UX_HOST_CLASS_GSER *gser;
77 UX_HOST_CLASS_GSER_RECEPTION *gser_reception;
78 ULONG interface_index;
79
80 /* Get the class instance for this transfer request. */
81 gser = (UX_HOST_CLASS_GSER *) transfer_request -> ux_transfer_request_class_instance;
82
83 /* The interface index was stored into the user specific field. */
84 interface_index = (ULONG) (ALIGN_TYPE) transfer_request -> ux_transfer_request_user_specific;
85
86 /* Get the pointer to the acm reception structure. */
87 gser_reception = gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_reception;
88
89 /* Check the state of the transfer. If there is an error, we do not proceed with this report. */
90 if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
91 {
92
93 /* The reception is stopped. */
94 gser_reception -> ux_host_class_gser_reception_state = UX_HOST_CLASS_GSER_RECEPTION_STATE_STOPPED;
95
96 /* We do not proceed. */
97 return;
98
99 }
100
101 /* And move to the next reception buffer. Check if we are at the end of the application buffer. */
102 if (gser_reception -> ux_host_class_gser_reception_data_head + gser_reception -> ux_host_class_gser_reception_block_size >=
103 gser_reception -> ux_host_class_gser_reception_data_buffer + gser_reception -> ux_host_class_gser_reception_data_buffer_size)
104 {
105
106 /* We are at the end of the buffer. Move back to the beginning if we have space available. */
107 if (gser_reception -> ux_host_class_gser_reception_data_tail == gser_reception -> ux_host_class_gser_reception_data_buffer)
108 {
109
110 /* Error trap. */
111 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW);
112
113 /* If trace is enabled, insert this event into the trace buffer. */
114 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_BUFFER_OVERFLOW, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0)
115
116 /* We have an overflow. We cannot continue. Report to the application. */
117 gser_reception -> ux_host_class_gser_reception_callback(gser, UX_BUFFER_OVERFLOW, UX_NULL, 0);
118
119 /* And stop the transfer in progress flag. */
120 gser_reception -> ux_host_class_gser_reception_state = UX_HOST_CLASS_GSER_RECEPTION_STATE_STOPPED;
121
122 return;
123 }
124 else
125
126 /* Program the head to be at the beginning of the application buffer. */
127 gser_reception -> ux_host_class_gser_reception_data_head = gser_reception -> ux_host_class_gser_reception_data_buffer;
128
129 }
130 else
131
132 /* Program the head to be after the current buffer. */
133 gser_reception -> ux_host_class_gser_reception_data_head += gser_reception -> ux_host_class_gser_reception_block_size;
134
135
136 /* We need to report this transfer to the application. */
137 gser_reception -> ux_host_class_gser_reception_callback(gser,
138 transfer_request -> ux_transfer_request_completion_code,
139 transfer_request -> ux_transfer_request_data_pointer,
140 transfer_request -> ux_transfer_request_actual_length);
141
142 /* Arm another transfer. */
143 _ux_host_stack_transfer_request(transfer_request);
144
145 /* There is no status to be reported back to the stack. */
146 return;
147 }
148
149