1 /* 2 * Copyright (c) 2024 Nordic Semiconductor ASA 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /* 8 * The macros in this file are not for public use, but only for HID driver 9 * instantiation. 10 */ 11 12 #include <zephyr/sys/util_macro.h> 13 #include <zephyr/usb/usb_ch9.h> 14 15 #ifndef ZEPHYR_USB_DEVICE_CLASS_HID_MACROS_H_ 16 #define ZEPHYR_USB_DEVICE_CLASS_HID_MACROS_H_ 17 18 /* 19 * This long list of definitions is used in HID_MPS_LESS_65 macro to determine 20 * whether an endpoint MPS is equal to or less than 64 bytes. 21 */ 22 #define HID_MPS_LESS_65_0 1 23 #define HID_MPS_LESS_65_1 1 24 #define HID_MPS_LESS_65_2 1 25 #define HID_MPS_LESS_65_3 1 26 #define HID_MPS_LESS_65_4 1 27 #define HID_MPS_LESS_65_5 1 28 #define HID_MPS_LESS_65_6 1 29 #define HID_MPS_LESS_65_7 1 30 #define HID_MPS_LESS_65_8 1 31 #define HID_MPS_LESS_65_9 1 32 #define HID_MPS_LESS_65_10 1 33 #define HID_MPS_LESS_65_11 1 34 #define HID_MPS_LESS_65_12 1 35 #define HID_MPS_LESS_65_13 1 36 #define HID_MPS_LESS_65_14 1 37 #define HID_MPS_LESS_65_15 1 38 #define HID_MPS_LESS_65_16 1 39 #define HID_MPS_LESS_65_17 1 40 #define HID_MPS_LESS_65_18 1 41 #define HID_MPS_LESS_65_19 1 42 #define HID_MPS_LESS_65_20 1 43 #define HID_MPS_LESS_65_21 1 44 #define HID_MPS_LESS_65_22 1 45 #define HID_MPS_LESS_65_23 1 46 #define HID_MPS_LESS_65_24 1 47 #define HID_MPS_LESS_65_25 1 48 #define HID_MPS_LESS_65_26 1 49 #define HID_MPS_LESS_65_27 1 50 #define HID_MPS_LESS_65_28 1 51 #define HID_MPS_LESS_65_29 1 52 #define HID_MPS_LESS_65_30 1 53 #define HID_MPS_LESS_65_31 1 54 #define HID_MPS_LESS_65_32 1 55 #define HID_MPS_LESS_65_33 1 56 #define HID_MPS_LESS_65_34 1 57 #define HID_MPS_LESS_65_35 1 58 #define HID_MPS_LESS_65_36 1 59 #define HID_MPS_LESS_65_37 1 60 #define HID_MPS_LESS_65_38 1 61 #define HID_MPS_LESS_65_39 1 62 #define HID_MPS_LESS_65_40 1 63 #define HID_MPS_LESS_65_41 1 64 #define HID_MPS_LESS_65_42 1 65 #define HID_MPS_LESS_65_43 1 66 #define HID_MPS_LESS_65_44 1 67 #define HID_MPS_LESS_65_45 1 68 #define HID_MPS_LESS_65_46 1 69 #define HID_MPS_LESS_65_47 1 70 #define HID_MPS_LESS_65_48 1 71 #define HID_MPS_LESS_65_49 1 72 #define HID_MPS_LESS_65_50 1 73 #define HID_MPS_LESS_65_51 1 74 #define HID_MPS_LESS_65_52 1 75 #define HID_MPS_LESS_65_53 1 76 #define HID_MPS_LESS_65_54 1 77 #define HID_MPS_LESS_65_55 1 78 #define HID_MPS_LESS_65_56 1 79 #define HID_MPS_LESS_65_57 1 80 #define HID_MPS_LESS_65_58 1 81 #define HID_MPS_LESS_65_59 1 82 #define HID_MPS_LESS_65_60 1 83 #define HID_MPS_LESS_65_61 1 84 #define HID_MPS_LESS_65_62 1 85 #define HID_MPS_LESS_65_63 1 86 #define HID_MPS_LESS_65_64 1 87 88 #define HID_MPS_LESS_65(x) UTIL_PRIMITIVE_CAT(HID_MPS_LESS_65_, x) 89 90 /* 91 * If all the endpoint MPS are less than 65 bytes, we do not need to define and 92 * configure an alternate interface. 93 */ 94 #define HID_ALL_MPS_LESS_65(n) \ 95 COND_CODE_1(HID_MPS_LESS_65(DT_INST_PROP_OR(n, out_report_size, 0)), \ 96 (HID_MPS_LESS_65(DT_INST_PROP(n, in_report_size))), (0)) 97 98 /* Get IN endpoint polling rate based on the desired speed. */ 99 #define HID_IN_EP_INTERVAL(n, hs) \ 100 COND_CODE_1(hs, \ 101 (USB_HS_INT_EP_INTERVAL(DT_INST_PROP(n, in_polling_period_us))), \ 102 (USB_FS_INT_EP_INTERVAL(DT_INST_PROP(n, in_polling_period_us)))) 103 104 /* Get OUT endpoint polling rate based on the desired speed. */ 105 #define HID_OUT_EP_INTERVAL(n, hs) \ 106 COND_CODE_1(hs, \ 107 (USB_HS_INT_EP_INTERVAL(DT_INST_PROP(n, out_polling_period_us))), \ 108 (USB_FS_INT_EP_INTERVAL(DT_INST_PROP(n, out_polling_period_us)))) 109 110 /* Get the number of endpoints, which can be either 1 or 2 */ 111 #define HID_NUM_ENDPOINTS(n) \ 112 COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), (2), (1)) 113 114 /* 115 * Either the device does not support a boot protocol, or it supports the 116 * keyboard or mouse boot protocol. 117 */ 118 #define HID_INTERFACE_PROTOCOL(n) DT_INST_ENUM_IDX_OR(n, protocol_code, 0) 119 120 /* bInterfaceSubClass must be set to 1 if a boot device protocol is supported */ 121 #define HID_INTERFACE_SUBCLASS(n) \ 122 COND_CODE_0(HID_INTERFACE_PROTOCOL(n), (0), (1)) 123 124 #define HID_INTERFACE_DEFINE(n, alt) \ 125 { \ 126 .bLength = sizeof(struct usb_if_descriptor), \ 127 .bDescriptorType = USB_DESC_INTERFACE, \ 128 .bInterfaceNumber = 0, \ 129 .bAlternateSetting = alt, \ 130 .bNumEndpoints = HID_NUM_ENDPOINTS(n), \ 131 .bInterfaceClass = USB_BCC_HID, \ 132 .bInterfaceSubClass = HID_INTERFACE_SUBCLASS(n), \ 133 .bInterfaceProtocol = HID_INTERFACE_PROTOCOL(n), \ 134 .iInterface = 0, \ 135 } 136 137 #define HID_DESCRIPTOR_DEFINE(n) \ 138 { \ 139 .bLength = sizeof(struct hid_descriptor), \ 140 .bDescriptorType = USB_DESC_HID, \ 141 .bcdHID = sys_cpu_to_le16(USB_HID_VERSION), \ 142 .bCountryCode = 0, \ 143 .bNumDescriptors = HID_SUBORDINATE_DESC_NUM, \ 144 .sub[0] = { \ 145 .bDescriptorType = USB_DESC_HID_REPORT, \ 146 .wDescriptorLength = 0, \ 147 }, \ 148 } \ 149 150 /* 151 * OUT endpoint MPS for either default or alternate interface. 152 * MPS for the default interface is always limited to 64 bytes. 153 */ 154 #define HID_OUT_EP_MPS(n, alt) \ 155 COND_CODE_1(alt, \ 156 (sys_cpu_to_le16(USB_TPL_TO_MPS(DT_INST_PROP(n, out_report_size)))), \ 157 (sys_cpu_to_le16(MIN(DT_INST_PROP(n, out_report_size), 64U)))) 158 159 /* 160 * IN endpoint MPS for either default or alternate interface. 161 * MPS for the default interface is always limited to 64 bytes. 162 */ 163 #define HID_IN_EP_MPS(n, alt) \ 164 COND_CODE_1(alt, \ 165 (sys_cpu_to_le16(USB_TPL_TO_MPS(DT_INST_PROP(n, in_report_size)))), \ 166 (sys_cpu_to_le16(MIN(DT_INST_PROP(n, in_report_size), 64U)))) 167 168 #define HID_OUT_EP_DEFINE(n, hs, alt) \ 169 { \ 170 .bLength = sizeof(struct usb_ep_descriptor), \ 171 .bDescriptorType = USB_DESC_ENDPOINT, \ 172 .bEndpointAddress = 0x01, \ 173 .bmAttributes = USB_EP_TYPE_INTERRUPT, \ 174 .wMaxPacketSize = HID_OUT_EP_MPS(n, alt), \ 175 .bInterval = HID_OUT_EP_INTERVAL(n, hs), \ 176 } 177 178 #define HID_IN_EP_DEFINE(n, hs, alt) \ 179 { \ 180 .bLength = sizeof(struct usb_ep_descriptor), \ 181 .bDescriptorType = USB_DESC_ENDPOINT, \ 182 .bEndpointAddress = 0x81, \ 183 .bmAttributes = USB_EP_TYPE_INTERRUPT, \ 184 .wMaxPacketSize = HID_IN_EP_MPS(n, alt), \ 185 .bInterval = HID_IN_EP_INTERVAL(n, hs), \ 186 } 187 188 /* 189 * Both the optional OUT endpoint and the associated pool are only defined if 190 * there is an out-report-size property. 191 */ 192 #define HID_OUT_EP_DEFINE_OR_ZERO(n, hs, alt) \ 193 COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), \ 194 (HID_OUT_EP_DEFINE(n, hs, alt)), \ 195 ({0})) 196 197 #define HID_OUT_POOL_DEFINE(n) \ 198 COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), \ 199 (UDC_BUF_POOL_DEFINE(hid_buf_pool_out_##n, \ 200 CONFIG_USBD_HID_OUT_BUF_COUNT, \ 201 DT_INST_PROP(n, out_report_size), \ 202 sizeof(struct udc_buf_info), NULL)), \ 203 ()) 204 205 #define HID_OUT_POOL_ADDR(n) \ 206 COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), \ 207 (&hid_buf_pool_out_##n), (NULL)) 208 209 #define HID_VERIFY_REPORT_SIZES(n) \ 210 BUILD_ASSERT(USB_TPL_IS_VALID(DT_INST_PROP_OR(n, out_report_size, 0)), \ 211 "out-report-size must be valid Total Packet Length"); \ 212 BUILD_ASSERT(USB_TPL_IS_VALID(DT_INST_PROP_OR(n, in_report_size, 0)), \ 213 "in-report-size must be valid Total Packet Length"); 214 215 #endif /* ZEPHYR_USB_DEVICE_CLASS_HID_MACROS_H_ */ 216