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 /** USBX Component */
15 /** */
16 /** Device Audio Class */
17 /** */
18 /**************************************************************************/
19 /**************************************************************************/
20
21 #define UX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "ux_api.h"
27 #include "ux_device_class_audio.h"
28 #include "ux_device_stack.h"
29
30
31 #if !defined(UX_DEVICE_STANDALONE) && defined(UX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT)
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _ux_device_class_audio_interrupt_thread_entry PORTABLE C */
37 /* 6.1.12 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function is thread of INTERRUPT IN from the Audio class. */
45 /* */
46 /* It's for RTOS mode. */
47 /* */
48 /* INPUT */
49 /* */
50 /* audio Address of audio instance */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* None */
55 /* */
56 /* CALLS */
57 /* */
58 /* _ux_system_error_handler System error trap */
59 /* _ux_device_thread_suspend Suspend thread used */
60 /* _ux_device_stack_transfer_request Issue transfer request */
61 /* _ux_utility_memory_copy Copy data */
62 /* */
63 /* CALLED BY */
64 /* */
65 /* ThreadX */
66 /* */
67 /* RELEASE HISTORY */
68 /* */
69 /* DATE NAME DESCRIPTION */
70 /* */
71 /* 07-29-2022 Chaoqiong Xiao Initial Version 6.1.12 */
72 /* */
73 /**************************************************************************/
_ux_device_class_audio_interrupt_thread_entry(ULONG audio_inst)74 VOID _ux_device_class_audio_interrupt_thread_entry(ULONG audio_inst)
75 {
76
77 UINT status;
78 UX_DEVICE_CLASS_AUDIO *audio;
79 UX_SLAVE_DEVICE *device;
80 UX_SLAVE_ENDPOINT *endpoint;
81 UX_SLAVE_TRANSFER *transfer;
82 ULONG size;
83 UCHAR *buff;
84
85
86 /* Get Audio class instance. */
87 UX_THREAD_EXTENSION_PTR_GET(audio, UX_DEVICE_CLASS_AUDIO, audio_inst)
88
89 /* Get stack device instance. */
90 device = audio -> ux_device_class_audio_device;
91
92 /* This thread runs forever but can be suspended or resumed. */
93 while(1)
94 {
95 while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED)
96 {
97
98 /* Get endpoint instance. */
99 endpoint = audio -> ux_device_class_audio_interrupt;
100
101 /* Endpoint not available, maybe it's alternate setting 0. */
102 if (endpoint == UX_NULL)
103 break;
104
105 /* Get transfer instance. */
106 transfer = &endpoint -> ux_slave_endpoint_transfer_request;
107
108 /* Get semaphore before start transfer. */
109 status = _ux_device_semaphore_get(&audio -> ux_device_class_audio_status_semaphore, UX_WAIT_FOREVER);
110 if (status != UX_SUCCESS)
111 {
112
113 /* Error notification! */
114 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_SEMAPHORE_ERROR);
115 break;
116 }
117
118 /* Get interrupt data size. */
119 size = audio -> ux_device_class_audio_status_size;
120 UX_ASSERT(size <= transfer -> ux_slave_transfer_request_transfer_length);
121
122 /* Copy data in tail. */
123 buff = audio -> ux_device_class_audio_status_tail;
124 _ux_utility_memory_copy(transfer -> ux_slave_transfer_request_data_pointer,
125 buff, size); /* Use case of memcpy is verified. */
126
127 /* Start frame transfer anyway. */
128 status = _ux_device_stack_transfer_request(transfer, size, size);
129
130 /* Check transfer status. */
131 if (status != UX_SUCCESS)
132 {
133
134 /* Error notification! */
135 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR);
136 break;
137 }
138
139 /* Calculate next tail. */
140 buff += size;
141 if (buff >= (audio -> ux_device_class_audio_status_queue + audio -> ux_device_class_audio_status_queue_bytes))
142 buff = audio -> ux_device_class_audio_status_queue;
143
144 /* Update queue status. */
145 _ux_device_mutex_on(&audio -> ux_device_class_audio_status_mutex);
146 audio -> ux_device_class_audio_status_tail = buff;
147 audio -> ux_device_class_audio_status_queued -= size;
148 _ux_device_mutex_off(&audio -> ux_device_class_audio_status_mutex);
149
150 } /* while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) */
151
152 /* We need to suspend ourselves. We will be resumed by the device enumeration module or when a change of alternate setting happens. */
153 _ux_device_thread_suspend(&audio -> ux_device_class_audio_class -> ux_slave_class_thread);
154 }
155 }
156 #endif
157