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