GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_hid_keyboard_entry.c Lines: 14 14 100.0 %
Date: 2026-03-06 18:57:10 Branches: 8 8 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 **************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** USBX Component                                                        */
17
/**                                                                       */
18
/**   HID Keyboard Client                                                 */
19
/**                                                                       */
20
/**************************************************************************/
21
/**************************************************************************/
22
23
24
/* Include necessary system files.  */
25
26
#define UX_SOURCE_CODE
27
28
#include "ux_api.h"
29
#include "ux_host_class_hid.h"
30
#include "ux_host_class_hid_keyboard.h"
31
#include "ux_host_stack.h"
32
33
34
#if defined(UX_HOST_STANDALONE)
35
36
#define UX_HOST_CLASS_HID_KEYBOARD_ENUM_START           (UX_STATE_WAIT)
37
#define UX_HOST_CLASS_HID_KEYBOARD_ENUM_SET_REPORT      (UX_STATE_STACK_STEP + 0)
38
#define UX_HOST_CLASS_HID_KEYBOARD_ENUM_SET_IDLE        (UX_STATE_STACK_STEP + 1)
39
#define UX_HOST_CLASS_HID_KEYBOARD_ENUM_CMD_WAIT        (UX_STATE_STACK_STEP + 2)
40
#define UX_HOST_CLASS_HID_KEYBOARD_ENUM_PERIODIC_START  (UX_STATE_STACK_STEP + 3)
41
#define UX_HOST_CLASS_HID_KEYBOARD_ENUM_DONE            (UX_STATE_STACK_STEP + 4)
42
43
44
static inline UINT  _ux_host_class_hid_keyboard_activate_wait(UX_HOST_CLASS_HID_CLIENT_COMMAND *command);
45
#endif
46
47
48
/**************************************************************************/
49
/*                                                                        */
50
/*  FUNCTION                                               RELEASE        */
51
/*                                                                        */
52
/*    _ux_host_class_hid_keyboard_entry                   PORTABLE C      */
53
/*                                                           6.1.10       */
54
/*  AUTHOR                                                                */
55
/*                                                                        */
56
/*    Chaoqiong Xiao, Microsoft Corporation                               */
57
/*                                                                        */
58
/*  DESCRIPTION                                                           */
59
/*                                                                        */
60
/*    This function is the entry point of the HID keyboard client.        */
61
/*    This function is called by the HID class after it has parsed a new  */
62
/*    HID report descriptor and is searching for a HID client.            */
63
/*                                                                        */
64
/*  INPUT                                                                 */
65
/*                                                                        */
66
/*    command                               Pointer to command            */
67
/*                                                                        */
68
/*  OUTPUT                                                                */
69
/*                                                                        */
70
/*    Completion Status                                                   */
71
/*                                                                        */
72
/*  CALLS                                                                 */
73
/*                                                                        */
74
/*    _ux_host_class_hid_keyboard_activate                                */
75
/*                                              Activate HID keyboard     */
76
/*    _ux_host_class_hid_keyboard_deactivate                              */
77
/*                                              Deactivate HID keyboard   */
78
/*                                                                        */
79
/*  CALLED BY                                                             */
80
/*                                                                        */
81
/*    HID Class                                                           */
82
/*                                                                        */
83
/**************************************************************************/
84
420
UINT  _ux_host_class_hid_keyboard_entry(UX_HOST_CLASS_HID_CLIENT_COMMAND *command)
85
{
86
87
UINT        status;
88
89
90
    /* The command request will tell us we need to do here, either a enumeration
91
       query, an activation or a deactivation.  */
92

420
    switch (command -> ux_host_class_hid_client_command_request)
93
    {
94
95
96
180
    case UX_HOST_CLASS_COMMAND_QUERY:
97
98
        /* The query command is used to let the HID class know if we want to own
99
           this device or not */
100
180
        if ((command -> ux_host_class_hid_client_command_page == UX_HOST_CLASS_HID_PAGE_GENERIC_DESKTOP_CONTROLS) &&
101
166
            (command -> ux_host_class_hid_client_command_usage == UX_HOST_CLASS_HID_GENERIC_DESKTOP_KEYBOARD))
102
163
            return(UX_SUCCESS);
103
        else
104
17
            return(UX_NO_CLASS_MATCH);
105
106
107
163
    case UX_HOST_CLASS_COMMAND_ACTIVATE:
108
109
        /* The activate command is used by the HID class to start the HID client.  */
110
163
        status =  _ux_host_class_hid_keyboard_activate(command);
111
112
        /* Return completion status.  */
113
163
        return(status);
114
115
116
#if defined(UX_HOST_STANDALONE)
117
    case UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT:
118
119
        return(_ux_host_class_hid_keyboard_activate_wait(command));
120
#endif
121
122
123
76
    case UX_HOST_CLASS_COMMAND_DEACTIVATE:
124
125
        /* The deactivate command is used by the HID class when it received a deactivate
126
           command from the USBX stack and there was a HID client attached to the HID instance */
127
76
        status =  _ux_host_class_hid_keyboard_deactivate(command);
128
129
        /* Return completion status.  */
130
76
        return(status);
131
    }
132
133
    /* Return error status.  */
134
1
    return(UX_ERROR);
135
}
136
137
#if defined(UX_HOST_STANDALONE)
138
static inline UINT _ux_host_class_hid_keyboard_activate_wait(UX_HOST_CLASS_HID_CLIENT_COMMAND *command)
139
{
140
141
UX_HOST_CLASS_HID                       *hid;
142
UX_HOST_CLASS_HID_CLIENT                *hid_client;
143
UX_HOST_CLASS_HID_KEYBOARD              *keyboard;
144
UINT                                    status;
145
146
    /* Get the instance to the HID class.  */
147
    hid = command -> ux_host_class_hid_client_command_instance;
148
149
    /* And of the HID client.  */
150
    hid_client = hid -> ux_host_class_hid_client;
151
152
    /* And of the keyboard instance.  */
153
    keyboard = (UX_HOST_CLASS_HID_KEYBOARD *) hid_client -> ux_host_class_hid_client_local_instance;
154
155
    /* Run states.  */
156
    switch(keyboard -> ux_host_class_hid_keyboard_enum_state)
157
    {
158
    case UX_HOST_CLASS_HID_KEYBOARD_ENUM_START:
159
    /* Fall through.  */
160
    case UX_HOST_CLASS_HID_KEYBOARD_ENUM_SET_REPORT:
161
162
        /* Update LED in task.  */
163
        keyboard -> ux_host_class_hid_keyboard_out_state = UX_STATE_WAIT;
164
        keyboard -> ux_host_class_hid_keyboard_enum_state =
165
                                    UX_HOST_CLASS_HID_KEYBOARD_ENUM_CMD_WAIT;
166
        keyboard -> ux_host_class_hid_keyboard_next_state =
167
                                    UX_HOST_CLASS_HID_KEYBOARD_ENUM_SET_IDLE;
168
        return(UX_STATE_WAIT);
169
170
    case UX_HOST_CLASS_HID_KEYBOARD_ENUM_CMD_WAIT:
171
172
        /* LEDs processed in background task.  */
173
        if (keyboard -> ux_host_class_hid_keyboard_out_state != UX_STATE_WAIT)
174
        {
175
            if (keyboard -> ux_host_class_hid_keyboard_status != UX_SUCCESS)
176
                keyboard -> ux_host_class_hid_keyboard_enum_state =
177
                                        UX_HOST_CLASS_HID_KEYBOARD_ENUM_DONE;
178
            else
179
                keyboard -> ux_host_class_hid_keyboard_enum_state =
180
                            keyboard -> ux_host_class_hid_keyboard_next_state;
181
        }
182
        return(UX_STATE_WAIT);
183
184
    case UX_HOST_CLASS_HID_KEYBOARD_ENUM_SET_IDLE:
185
186
        /* Run SET_IDLE states.  */
187
        status = _ux_host_class_hid_idle_set_run(hid, 0,
188
                            keyboard -> ux_host_class_hid_keyboard_id);
189
        if (status < UX_STATE_WAIT)
190
        {
191
            keyboard -> ux_host_class_hid_keyboard_status =
192
                                hid -> ux_host_class_hid_status;
193
194
            /* Set_Idle is mandatory, if there is error enum fail.  */
195
            if (keyboard -> ux_host_class_hid_keyboard_status == UX_SUCCESS)
196
                keyboard -> ux_host_class_hid_keyboard_enum_state =
197
                                UX_HOST_CLASS_HID_KEYBOARD_ENUM_PERIODIC_START;
198
            else
199
                keyboard -> ux_host_class_hid_keyboard_enum_state =
200
                                UX_HOST_CLASS_HID_KEYBOARD_ENUM_DONE;
201
202
        }
203
        return(UX_STATE_WAIT);
204
205
    case UX_HOST_CLASS_HID_KEYBOARD_ENUM_PERIODIC_START:
206
207
        /* Start the periodic report.  */
208
        status =  _ux_host_class_hid_periodic_report_start(hid);
209
        keyboard -> ux_host_class_hid_keyboard_status = status;
210
211
        /* Fall through.  */
212
    case UX_HOST_CLASS_HID_KEYBOARD_ENUM_DONE:
213
214
        /* Anything failed, Free resources.  */
215
        if (keyboard -> ux_host_class_hid_keyboard_status != UX_SUCCESS)
216
        {
217
218
            /* Detach instance.  */
219
            hid_client -> ux_host_class_hid_client_local_instance = UX_NULL;
220
221
            /* Free usage state.  */
222
            if (keyboard -> ux_host_class_hid_keyboard_key_state)
223
                _ux_utility_memory_free(keyboard -> ux_host_class_hid_keyboard_key_state);
224
225
            /* Free usage array.  */
226
            if (keyboard -> ux_host_class_hid_keyboard_usage_array)
227
                _ux_utility_memory_free(keyboard -> ux_host_class_hid_keyboard_usage_array);
228
229
            /* Free instance.  */
230
            _ux_utility_memory_free(keyboard);
231
232
            return(UX_STATE_ERROR);
233
        }
234
235
        /* Now keyboard instance is live.  */
236
        keyboard -> ux_host_class_hid_keyboard_state =  UX_HOST_CLASS_INSTANCE_LIVE;
237
238
        /* If all is fine and the device is mounted, we may need to inform the application
239
            if a function has been programmed in the system structure.  */
240
        if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
241
        {
242
243
            /* Call system change function.  */
244
            _ux_system_host ->  ux_system_host_change_function(UX_HID_CLIENT_INSERTION, hid -> ux_host_class_hid_class, (VOID *) hid_client);
245
        }
246
247
        /* If trace is enabled, insert this event into the trace buffer.  */
248
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_KEYBOARD_ACTIVATE, hid, keyboard, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
249
250
        /* Enumeration idle.  */
251
        keyboard -> ux_host_class_hid_keyboard_enum_state = UX_STATE_IDLE;
252
        return(UX_STATE_NEXT);
253
254
    default: /* IDLE, Other states.  */
255
        return(UX_STATE_NEXT);
256
    }
257
}
258
#endif