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 /**                                                                       */
16 /** USBX Component                                                        */
17 /**                                                                       */
18 /**  HID Class                                                            */
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_stack.h"
31 
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _ux_host_class_hid_interrupt_endpoint_search        PORTABLE C      */
38 /*                                                           6.1.12       */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Chaoqiong Xiao, Microsoft Corporation                               */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function searches for the handle of the only interrupt         */
46 /*    endpoint in the default alternate setting of the HID interface.     */
47 /*    The interrupt endpoint should always be there. The actual first     */
48 /*    transfer on the interrupt endpoint does not start until a HID       */
49 /*    client has claimed ownership of the HID device.                     */
50 /*                                                                        */
51 /*  INPUT                                                                 */
52 /*                                                                        */
53 /*    hid                                   Pointer to HID class          */
54 /*                                                                        */
55 /*  OUTPUT                                                                */
56 /*                                                                        */
57 /*    Completion Status                                                   */
58 /*                                                                        */
59 /*  CALLS                                                                 */
60 /*                                                                        */
61 /*    _ux_utility_memory_allocate           Allocate memory block         */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*    HID 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 /*                                            resulting in version 6.1    */
74 /*  01-31-2022     Xiuwen Cai, CQ Xiao      Modified comment(s),          */
75 /*                                            added interrupt OUT support,*/
76 /*                                            added timeout initialize,   */
77 /*                                            resulting in version 6.1.10 */
78 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
79 /*                                            fixed parameter/variable    */
80 /*                                            names conflict C++ keyword, */
81 /*                                            resulting in version 6.1.12 */
82 /*                                                                        */
83 /**************************************************************************/
_ux_host_class_hid_interrupt_endpoint_search(UX_HOST_CLASS_HID * hid)84 UINT  _ux_host_class_hid_interrupt_endpoint_search(UX_HOST_CLASS_HID *hid)
85 {
86 
87 UINT            status = UX_ENDPOINT_HANDLE_UNKNOWN;
88 UX_INTERFACE    *interface_ptr;
89 UX_ENDPOINT     *endpoint;
90 UX_TRANSFER     *transfer_request;
91 
92 
93     /* Search the interrupt endpoint. It is attached to the interface container.  */
94     interface_ptr = hid -> ux_host_class_hid_interface;
95     endpoint = interface_ptr -> ux_interface_first_endpoint;
96     while(endpoint != UX_NULL)
97     {
98 
99         /* Find interrupt IN endpoint.  */
100         if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) &&
101             ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT))
102         {
103 
104             /* The endpoint is correct, save it.  */
105             hid -> ux_host_class_hid_interrupt_endpoint = endpoint;
106 
107             /* Fill in the transfer request with the length requested for this endpoint.  */
108             transfer_request =  &endpoint -> ux_endpoint_transfer_request;
109             transfer_request -> ux_transfer_request_requested_length =  hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_descriptor.wMaxPacketSize;
110             transfer_request -> ux_transfer_request_actual_length =     0;
111 
112             /* The direction is always IN for the HID interrupt endpoint.  */
113             transfer_request -> ux_transfer_request_type =  UX_REQUEST_IN;
114 
115             /* There is a callback function associated with the transfer request, so we need the class instance.  */
116             transfer_request -> ux_transfer_request_class_instance =  (VOID *) hid;
117 
118             /* Interrupt transactions have a completion routine. */
119             transfer_request -> ux_transfer_request_completion_function =  _ux_host_class_hid_transfer_request_completed;
120 
121             /* Transfer timeout : wait forever.  */
122             transfer_request -> ux_transfer_request_timeout_value = UX_WAIT_FOREVER;
123 
124             /* Obtain a buffer for this transaction. The buffer will always be reused.  */
125             transfer_request -> ux_transfer_request_data_pointer =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY,
126                                                                         transfer_request -> ux_transfer_request_requested_length);
127 
128             /* If the endpoint is available and we have memory, we mark the interrupt endpoint as ready.  */
129             if (transfer_request -> ux_transfer_request_data_pointer != UX_NULL)
130             {
131                 hid -> ux_host_class_hid_interrupt_endpoint_status =  UX_HOST_CLASS_HID_INTERRUPT_ENDPOINT_READY;
132                 status = UX_SUCCESS;
133 #if !defined(UX_HOST_CLASS_HID_INTERRUPT_OUT_SUPPORT)
134 
135                 /* We have found the interrupt IN endpoint, just stop searching.  */
136                 break;
137 #endif
138             }
139             else
140             {
141                 status = UX_MEMORY_INSUFFICIENT;
142                 break;
143             }
144         }
145 #if defined(UX_HOST_CLASS_HID_INTERRUPT_OUT_SUPPORT)
146         else if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) &&
147             ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT))
148         {
149 
150             /* Found the interrupt OUT endpoint, save it.  */
151             hid -> ux_host_class_hid_interrupt_out_endpoint = endpoint;
152         }
153 #endif
154 
155         /* Check next endpoint.  */
156         endpoint = endpoint -> ux_endpoint_next_endpoint;
157     }
158 
159     /* Return completion status.  */
160     return(status);
161 }
162 
163