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 CCID 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_ccid.h"
28 #include "ux_device_stack.h"
29 
30 
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _ux_device_class_ccid_control_request               PORTABLE C      */
36 /*                                                           6.1.11       */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Chaoqiong Xiao, Microsoft Corporation                               */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function manages the requests sent by the host on the control  */
44 /*    endpoints with a CLASS or VENDOR SPECIFIC type.                     */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    ccid                                  Pointer to ccid class         */
49 /*                                                                        */
50 /*  OUTPUT                                                                */
51 /*                                                                        */
52 /*    None                                                                */
53 /*                                                                        */
54 /*  CALLS                                                                 */
55 /*                                                                        */
56 /*    _ux_device_stack_transfer_request     Transfer request              */
57 /*    _ux_device_class_ccid_request_abort   Abort slot                    */
58 /*    _ux_utility_memory_copy               Copy memory                   */
59 /*                                                                        */
60 /*  CALLED BY                                                             */
61 /*                                                                        */
62 /*    CCID Class                                                          */
63 /*                                                                        */
64 /*  RELEASE HISTORY                                                       */
65 /*                                                                        */
66 /*    DATE              NAME                      DESCRIPTION             */
67 /*                                                                        */
68 /*  04-25-2022     Chaoqiong Xiao           Initial Version 6.1.11        */
69 /*                                                                        */
70 /**************************************************************************/
_ux_device_class_ccid_control_request(UX_SLAVE_CLASS_COMMAND * command)71 UINT  _ux_device_class_ccid_control_request(UX_SLAVE_CLASS_COMMAND *command)
72 {
73 UX_DEVICE_CLASS_CCID                    *ccid;
74 UX_DEVICE_CLASS_CCID_PARAMETER          *parameter;
75 UX_SLAVE_CLASS                          *ccid_class;
76 UX_SLAVE_TRANSFER                       *transfer_request;
77 UX_SLAVE_DEVICE                         *device;
78 ULONG                                   request;
79 UCHAR                                   seq, slot;
80 ULONG                                   request_length;
81 ULONG                                   transmit_length;
82 UCHAR                                   *transmit_buffer;
83 
84     /* Get the class container.  */
85     ccid_class =  command -> ux_slave_class_command_class_ptr;
86 
87     /* Get the class instance in the container.  */
88     ccid = (UX_DEVICE_CLASS_CCID *) ccid_class -> ux_slave_class_instance;
89 
90     /* Get the pointer to the device.  */
91     device =  &_ux_system_slave -> ux_system_slave_device;
92 
93     /* Get the pointer to the transfer request associated with the control endpoint.  */
94     transfer_request =  &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request;
95 
96     /* Extract all necessary fields of the request.  */
97     request =  *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST);
98 
99     /* Pickup the request length.  */
100     request_length =   _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH);
101 
102     /* Here we proceed only the standard request we know of at the device level.  */
103     switch (request)
104     {
105 
106     case UX_DEVICE_CLASS_CCID_ABORT:
107         slot = transfer_request -> ux_slave_transfer_request_setup[UX_SETUP_VALUE];
108         seq = transfer_request -> ux_slave_transfer_request_setup[UX_SETUP_VALUE + 1];
109         return _ux_device_class_ccid_control_abort(ccid, slot, seq);
110 
111     case UX_DEVICE_CLASS_CCID_GET_CLOCK_FREQUENCIES:
112         parameter = &ccid -> ux_device_class_ccid_parameter;
113 
114         /* Check bNumClockSuppored.  */
115         if (parameter -> ux_device_class_ccid_clocks == UX_NULL ||
116             parameter -> ux_device_class_ccid_n_clocks == 0)
117             return(UX_ERROR);
118 
119         /* Calculate transmit length.  */
120         transmit_length = parameter -> ux_device_class_ccid_n_clocks;
121         if (UX_OVERFLOW_CHECK_MULC_ULONG(transmit_length, 4))
122             return(UX_ERROR);
123         transmit_length <<= 2;
124 
125         /* Update transmit buffer.  */
126         transmit_buffer = (UCHAR *)parameter -> ux_device_class_ccid_clocks;
127         break;
128 
129     case UX_DEVICE_CLASS_CCID_GET_DATA_RATES:
130         parameter = &ccid -> ux_device_class_ccid_parameter;
131 
132         /* Check bNumDataRateSuppored.  */
133         if (parameter -> ux_device_class_ccid_data_rates == UX_NULL ||
134             parameter -> ux_device_class_ccid_n_data_rates == 0)
135             return(UX_ERROR);
136 
137         /* Calculate transmit length.  */
138         transmit_length = parameter -> ux_device_class_ccid_n_data_rates;
139         if (UX_OVERFLOW_CHECK_MULC_ULONG(transmit_length, 4))
140             return(UX_ERROR);
141         transmit_length <<= 2;
142 
143         /* Update transmit buffer.  */
144         transmit_buffer = (UCHAR *)parameter -> ux_device_class_ccid_data_rates;
145         break ;
146 
147     default:
148 
149         /* Unknown function. It's not handled.  */
150         return(UX_ERROR);
151     }
152 
153     /* Limit transmit length.  */
154     transmit_length = UX_MIN(transmit_length, UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH);
155     transmit_length = UX_MIN(transmit_length, request_length);
156 
157     /* Copy data to transmit.  */
158     _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer,
159             transmit_buffer, transmit_length); /* Use case of memcpy is verified. */
160 
161     /* Transmit.  */
162     _ux_device_stack_transfer_request(transfer_request, transmit_length, request_length);
163 
164     /* It's handled.  */
165     return(UX_SUCCESS);
166 }
167