1a46c0ec8Sopenharmony_ci/* 2a46c0ec8Sopenharmony_ci * Copyright © 2018 Red Hat, Inc. 3a46c0ec8Sopenharmony_ci * 4a46c0ec8Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5a46c0ec8Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6a46c0ec8Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7a46c0ec8Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8a46c0ec8Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9a46c0ec8Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10a46c0ec8Sopenharmony_ci * 11a46c0ec8Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12a46c0ec8Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13a46c0ec8Sopenharmony_ci * Software. 14a46c0ec8Sopenharmony_ci * 15a46c0ec8Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16a46c0ec8Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17a46c0ec8Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18a46c0ec8Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19a46c0ec8Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20a46c0ec8Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21a46c0ec8Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 22a46c0ec8Sopenharmony_ci */ 23a46c0ec8Sopenharmony_ci 24a46c0ec8Sopenharmony_ci#pragma once 25a46c0ec8Sopenharmony_ci 26a46c0ec8Sopenharmony_ci#include "config.h" 27a46c0ec8Sopenharmony_ci 28a46c0ec8Sopenharmony_ci#include <stdbool.h> 29a46c0ec8Sopenharmony_ci#include <stdint.h> 30a46c0ec8Sopenharmony_ci 31a46c0ec8Sopenharmony_ci#include <libudev.h> 32a46c0ec8Sopenharmony_ci 33a46c0ec8Sopenharmony_ci#include "libinput.h" 34a46c0ec8Sopenharmony_ci 35a46c0ec8Sopenharmony_ci/** 36a46c0ec8Sopenharmony_ci * Handle to the quirks context. 37a46c0ec8Sopenharmony_ci */ 38a46c0ec8Sopenharmony_cistruct quirks_context; 39a46c0ec8Sopenharmony_ci 40a46c0ec8Sopenharmony_ci/** 41a46c0ec8Sopenharmony_ci * Contains all quirks set for a single device. 42a46c0ec8Sopenharmony_ci */ 43a46c0ec8Sopenharmony_cistruct quirks; 44a46c0ec8Sopenharmony_ci 45a46c0ec8Sopenharmony_cistruct quirk_dimensions { 46a46c0ec8Sopenharmony_ci size_t x, y; 47a46c0ec8Sopenharmony_ci}; 48a46c0ec8Sopenharmony_ci 49a46c0ec8Sopenharmony_cistruct quirk_range { 50a46c0ec8Sopenharmony_ci int lower, upper; 51a46c0ec8Sopenharmony_ci}; 52a46c0ec8Sopenharmony_ci 53a46c0ec8Sopenharmony_cistruct quirk_tuples { 54a46c0ec8Sopenharmony_ci struct { 55a46c0ec8Sopenharmony_ci int first; 56a46c0ec8Sopenharmony_ci int second; 57a46c0ec8Sopenharmony_ci int third; 58a46c0ec8Sopenharmony_ci } tuples[32]; 59a46c0ec8Sopenharmony_ci size_t ntuples; 60a46c0ec8Sopenharmony_ci}; 61a46c0ec8Sopenharmony_ci 62a46c0ec8Sopenharmony_ci/** 63a46c0ec8Sopenharmony_ci * Quirks known to libinput 64a46c0ec8Sopenharmony_ci */ 65a46c0ec8Sopenharmony_cienum quirk { 66a46c0ec8Sopenharmony_ci QUIRK_MODEL_ALPS_SERIAL_TOUCHPAD = 100, 67a46c0ec8Sopenharmony_ci QUIRK_MODEL_APPLE_TOUCHPAD, 68a46c0ec8Sopenharmony_ci QUIRK_MODEL_APPLE_TOUCHPAD_ONEBUTTON, 69a46c0ec8Sopenharmony_ci QUIRK_MODEL_BOUNCING_KEYS, 70a46c0ec8Sopenharmony_ci QUIRK_MODEL_CHROMEBOOK, 71a46c0ec8Sopenharmony_ci QUIRK_MODEL_CLEVO_W740SU, 72a46c0ec8Sopenharmony_ci QUIRK_MODEL_DELL_CANVAS_TOTEM, 73a46c0ec8Sopenharmony_ci QUIRK_MODEL_HP_PAVILION_DM4_TOUCHPAD, 74a46c0ec8Sopenharmony_ci QUIRK_MODEL_HP_ZBOOK_STUDIO_G3, 75a46c0ec8Sopenharmony_ci QUIRK_MODEL_INVERT_HORIZONTAL_SCROLLING, 76a46c0ec8Sopenharmony_ci QUIRK_MODEL_LENOVO_SCROLLPOINT, 77a46c0ec8Sopenharmony_ci QUIRK_MODEL_LENOVO_T450_TOUCHPAD, 78a46c0ec8Sopenharmony_ci QUIRK_MODEL_LENOVO_X1GEN6_TOUCHPAD, 79a46c0ec8Sopenharmony_ci QUIRK_MODEL_LENOVO_X230, 80a46c0ec8Sopenharmony_ci QUIRK_MODEL_SYNAPTICS_SERIAL_TOUCHPAD, 81a46c0ec8Sopenharmony_ci QUIRK_MODEL_SYSTEM76_BONOBO, 82a46c0ec8Sopenharmony_ci QUIRK_MODEL_SYSTEM76_GALAGO, 83a46c0ec8Sopenharmony_ci QUIRK_MODEL_SYSTEM76_KUDU, 84a46c0ec8Sopenharmony_ci QUIRK_MODEL_TABLET_MODE_NO_SUSPEND, 85a46c0ec8Sopenharmony_ci QUIRK_MODEL_TABLET_MODE_SWITCH_UNRELIABLE, 86a46c0ec8Sopenharmony_ci QUIRK_MODEL_TOUCHPAD_VISIBLE_MARKER, 87a46c0ec8Sopenharmony_ci QUIRK_MODEL_TRACKBALL, 88a46c0ec8Sopenharmony_ci QUIRK_MODEL_WACOM_TOUCHPAD, 89a46c0ec8Sopenharmony_ci QUIRK_MODEL_PRESSURE_PAD, 90a46c0ec8Sopenharmony_ci QUIRK_MODEL_TOUCHPAD_PHANTOM_CLICKS, 91a46c0ec8Sopenharmony_ci 92a46c0ec8Sopenharmony_ci _QUIRK_LAST_MODEL_QUIRK_, /* Guard: do not modify */ 93a46c0ec8Sopenharmony_ci 94a46c0ec8Sopenharmony_ci QUIRK_ATTR_SIZE_HINT = 300, 95a46c0ec8Sopenharmony_ci QUIRK_ATTR_TOUCH_SIZE_RANGE, 96a46c0ec8Sopenharmony_ci QUIRK_ATTR_PALM_SIZE_THRESHOLD, 97a46c0ec8Sopenharmony_ci QUIRK_ATTR_LID_SWITCH_RELIABILITY, 98a46c0ec8Sopenharmony_ci QUIRK_ATTR_KEYBOARD_INTEGRATION, 99a46c0ec8Sopenharmony_ci QUIRK_ATTR_TRACKPOINT_INTEGRATION, 100a46c0ec8Sopenharmony_ci QUIRK_ATTR_TPKBCOMBO_LAYOUT, 101a46c0ec8Sopenharmony_ci QUIRK_ATTR_PRESSURE_RANGE, 102a46c0ec8Sopenharmony_ci QUIRK_ATTR_PALM_PRESSURE_THRESHOLD, 103a46c0ec8Sopenharmony_ci QUIRK_ATTR_RESOLUTION_HINT, 104a46c0ec8Sopenharmony_ci QUIRK_ATTR_TRACKPOINT_MULTIPLIER, 105a46c0ec8Sopenharmony_ci QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD, 106a46c0ec8Sopenharmony_ci QUIRK_ATTR_USE_VELOCITY_AVERAGING, 107a46c0ec8Sopenharmony_ci QUIRK_ATTR_TABLET_SMOOTHING, 108a46c0ec8Sopenharmony_ci QUIRK_ATTR_THUMB_SIZE_THRESHOLD, 109a46c0ec8Sopenharmony_ci QUIRK_ATTR_MSC_TIMESTAMP, 110a46c0ec8Sopenharmony_ci QUIRK_ATTR_EVENT_CODE, 111a46c0ec8Sopenharmony_ci QUIRK_ATTR_INPUT_PROP, 112a46c0ec8Sopenharmony_ci 113a46c0ec8Sopenharmony_ci _QUIRK_LAST_ATTR_QUIRK_, /* Guard: do not modify */ 114a46c0ec8Sopenharmony_ci}; 115a46c0ec8Sopenharmony_ci 116a46c0ec8Sopenharmony_ci/** 117a46c0ec8Sopenharmony_ci * Returns a printable name for the quirk. This name is for developer 118a46c0ec8Sopenharmony_ci * tools, not user consumption. Do not display this in a GUI. 119a46c0ec8Sopenharmony_ci */ 120a46c0ec8Sopenharmony_ciconst char* 121a46c0ec8Sopenharmony_ciquirk_get_name(enum quirk q); 122a46c0ec8Sopenharmony_ci 123a46c0ec8Sopenharmony_ci/** 124a46c0ec8Sopenharmony_ci * Log priorities used if custom logging is enabled. 125a46c0ec8Sopenharmony_ci */ 126a46c0ec8Sopenharmony_cienum quirks_log_priorities { 127a46c0ec8Sopenharmony_ci QLOG_NOISE, 128a46c0ec8Sopenharmony_ci QLOG_DEBUG = LIBINPUT_LOG_PRIORITY_DEBUG, 129a46c0ec8Sopenharmony_ci QLOG_INFO = LIBINPUT_LOG_PRIORITY_INFO, 130a46c0ec8Sopenharmony_ci QLOG_ERROR = LIBINPUT_LOG_PRIORITY_ERROR, 131a46c0ec8Sopenharmony_ci QLOG_PARSER_ERROR, 132a46c0ec8Sopenharmony_ci}; 133a46c0ec8Sopenharmony_ci 134a46c0ec8Sopenharmony_ci/** 135a46c0ec8Sopenharmony_ci * Log type to be used for logging. Use the libinput logging to hook up a 136a46c0ec8Sopenharmony_ci * libinput log handler. This will cause the quirks to reduce the noise and 137a46c0ec8Sopenharmony_ci * only provide useful messages. 138a46c0ec8Sopenharmony_ci * 139a46c0ec8Sopenharmony_ci * QLOG_CUSTOM_LOG_PRIORITIES enables more fine-grained and verbose logging, 140a46c0ec8Sopenharmony_ci * allowing debugging tools to be more useful. 141a46c0ec8Sopenharmony_ci */ 142a46c0ec8Sopenharmony_cienum quirks_log_type { 143a46c0ec8Sopenharmony_ci QLOG_LIBINPUT_LOGGING, 144a46c0ec8Sopenharmony_ci QLOG_CUSTOM_LOG_PRIORITIES, 145a46c0ec8Sopenharmony_ci}; 146a46c0ec8Sopenharmony_ci 147a46c0ec8Sopenharmony_ci/** 148a46c0ec8Sopenharmony_ci * Initialize the quirks subsystem. This function must be called 149a46c0ec8Sopenharmony_ci * before anything else. 150a46c0ec8Sopenharmony_ci * 151a46c0ec8Sopenharmony_ci * If log_type is QLOG_CUSTOM_LOG_PRIORITIES, the log handler is called with 152a46c0ec8Sopenharmony_ci * the custom QLOG_* log priorities. Otherwise, the log handler only uses 153a46c0ec8Sopenharmony_ci * the libinput log priorities. 154a46c0ec8Sopenharmony_ci * 155a46c0ec8Sopenharmony_ci * @param data_path The directory containing the various data files 156a46c0ec8Sopenharmony_ci * @param override_file A file path containing custom overrides 157a46c0ec8Sopenharmony_ci * @param log_handler The libinput log handler called for debugging output 158a46c0ec8Sopenharmony_ci * @param libinput The libinput struct passed to the log handler 159a46c0ec8Sopenharmony_ci * 160a46c0ec8Sopenharmony_ci * @return an opaque handle to the context 161a46c0ec8Sopenharmony_ci */ 162a46c0ec8Sopenharmony_cistruct quirks_context * 163a46c0ec8Sopenharmony_ciquirks_init_subsystem(const char *data_path, 164a46c0ec8Sopenharmony_ci const char *override_file, 165a46c0ec8Sopenharmony_ci libinput_log_handler log_handler, 166a46c0ec8Sopenharmony_ci struct libinput *libinput, 167a46c0ec8Sopenharmony_ci enum quirks_log_type log_type); 168a46c0ec8Sopenharmony_ci 169a46c0ec8Sopenharmony_ci/** 170a46c0ec8Sopenharmony_ci * Clean up after ourselves. This function must be called 171a46c0ec8Sopenharmony_ci * as the last call to the quirks subsystem. 172a46c0ec8Sopenharmony_ci * 173a46c0ec8Sopenharmony_ci * All quirks returned to the caller in quirks_fetch_for_device() must be 174a46c0ec8Sopenharmony_ci * unref'd before this call. 175a46c0ec8Sopenharmony_ci * 176a46c0ec8Sopenharmony_ci * @return Always NULL 177a46c0ec8Sopenharmony_ci */ 178a46c0ec8Sopenharmony_cistruct quirks_context * 179a46c0ec8Sopenharmony_ciquirks_context_unref(struct quirks_context *ctx); 180a46c0ec8Sopenharmony_ci 181a46c0ec8Sopenharmony_cistruct quirks_context * 182a46c0ec8Sopenharmony_ciquirks_context_ref(struct quirks_context *ctx); 183a46c0ec8Sopenharmony_ci 184a46c0ec8Sopenharmony_ci/** 185a46c0ec8Sopenharmony_ci * Fetch the quirks for a given device. If no quirks are defined, this 186a46c0ec8Sopenharmony_ci * function returns NULL. 187a46c0ec8Sopenharmony_ci * 188a46c0ec8Sopenharmony_ci * @return A new quirks struct, use quirks_unref() to release 189a46c0ec8Sopenharmony_ci */ 190a46c0ec8Sopenharmony_cistruct quirks * 191a46c0ec8Sopenharmony_ciquirks_fetch_for_device(struct quirks_context *ctx, 192a46c0ec8Sopenharmony_ci struct udev_device *device); 193a46c0ec8Sopenharmony_ci 194a46c0ec8Sopenharmony_ci/** 195a46c0ec8Sopenharmony_ci * Reduce the refcount by one. When the refcount reaches zero, the 196a46c0ec8Sopenharmony_ci * associated struct is released. 197a46c0ec8Sopenharmony_ci * 198a46c0ec8Sopenharmony_ci * @return Always NULL 199a46c0ec8Sopenharmony_ci */ 200a46c0ec8Sopenharmony_cistruct quirks * 201a46c0ec8Sopenharmony_ciquirks_unref(struct quirks *q); 202a46c0ec8Sopenharmony_ci 203a46c0ec8Sopenharmony_ci/** 204a46c0ec8Sopenharmony_ci * Returns true if the given quirk applies is in this quirk list. 205a46c0ec8Sopenharmony_ci */ 206a46c0ec8Sopenharmony_cibool 207a46c0ec8Sopenharmony_ciquirks_has_quirk(struct quirks *q, enum quirk which); 208a46c0ec8Sopenharmony_ci 209a46c0ec8Sopenharmony_ci/** 210a46c0ec8Sopenharmony_ci * Get the value of the given quirk, as unsigned integer. 211a46c0ec8Sopenharmony_ci * This function will assert if the quirk type does not match the 212a46c0ec8Sopenharmony_ci * requested type. If the quirk is not set for this device, val is 213a46c0ec8Sopenharmony_ci * unchanged. 214a46c0ec8Sopenharmony_ci * 215a46c0ec8Sopenharmony_ci * @return true if the quirk value is valid, false otherwise. 216a46c0ec8Sopenharmony_ci */ 217a46c0ec8Sopenharmony_cibool 218a46c0ec8Sopenharmony_ciquirks_get_uint32(struct quirks *q, 219a46c0ec8Sopenharmony_ci enum quirk which, 220a46c0ec8Sopenharmony_ci uint32_t *val); 221a46c0ec8Sopenharmony_ci 222a46c0ec8Sopenharmony_ci/** 223a46c0ec8Sopenharmony_ci * Get the value of the given quirk, as signed integer. 224a46c0ec8Sopenharmony_ci * This function will assert if the quirk type does not match the 225a46c0ec8Sopenharmony_ci * requested type. If the quirk is not set for this device, val is 226a46c0ec8Sopenharmony_ci * unchanged. 227a46c0ec8Sopenharmony_ci * 228a46c0ec8Sopenharmony_ci * @return true if the quirk value is valid, false otherwise. 229a46c0ec8Sopenharmony_ci */ 230a46c0ec8Sopenharmony_cibool 231a46c0ec8Sopenharmony_ciquirks_get_int32(struct quirks *q, 232a46c0ec8Sopenharmony_ci enum quirk which, 233a46c0ec8Sopenharmony_ci int32_t *val); 234a46c0ec8Sopenharmony_ci 235a46c0ec8Sopenharmony_ci/** 236a46c0ec8Sopenharmony_ci * Get the value of the given quirk, as double. 237a46c0ec8Sopenharmony_ci * This function will assert if the quirk type does not match the 238a46c0ec8Sopenharmony_ci * requested type. If the quirk is not set for this device, val is 239a46c0ec8Sopenharmony_ci * unchanged. 240a46c0ec8Sopenharmony_ci * 241a46c0ec8Sopenharmony_ci * @return true if the quirk value is valid, false otherwise. 242a46c0ec8Sopenharmony_ci */ 243a46c0ec8Sopenharmony_cibool 244a46c0ec8Sopenharmony_ciquirks_get_double(struct quirks *q, 245a46c0ec8Sopenharmony_ci enum quirk which, 246a46c0ec8Sopenharmony_ci double *val); 247a46c0ec8Sopenharmony_ci 248a46c0ec8Sopenharmony_ci/** 249a46c0ec8Sopenharmony_ci * Get the value of the given quirk, as string. 250a46c0ec8Sopenharmony_ci * This function will assert if the quirk type does not match the 251a46c0ec8Sopenharmony_ci * requested type. If the quirk is not set for this device, val is 252a46c0ec8Sopenharmony_ci * unchanged. 253a46c0ec8Sopenharmony_ci * 254a46c0ec8Sopenharmony_ci * val is set to the string, do not modify or free it. The lifetime of the 255a46c0ec8Sopenharmony_ci * returned string is bound to the lifetime of the quirk. 256a46c0ec8Sopenharmony_ci * 257a46c0ec8Sopenharmony_ci * @return true if the quirk value is valid, false otherwise. 258a46c0ec8Sopenharmony_ci */ 259a46c0ec8Sopenharmony_cibool 260a46c0ec8Sopenharmony_ciquirks_get_string(struct quirks *q, 261a46c0ec8Sopenharmony_ci enum quirk which, 262a46c0ec8Sopenharmony_ci char **val); 263a46c0ec8Sopenharmony_ci 264a46c0ec8Sopenharmony_ci/** 265a46c0ec8Sopenharmony_ci * Get the value of the given quirk, as bool. 266a46c0ec8Sopenharmony_ci * This function will assert if the quirk type does not match the 267a46c0ec8Sopenharmony_ci * requested type. If the quirk is not set for this device, val is 268a46c0ec8Sopenharmony_ci * unchanged. 269a46c0ec8Sopenharmony_ci * 270a46c0ec8Sopenharmony_ci * @return true if the quirk value is valid, false otherwise. 271a46c0ec8Sopenharmony_ci */ 272a46c0ec8Sopenharmony_cibool 273a46c0ec8Sopenharmony_ciquirks_get_bool(struct quirks *q, 274a46c0ec8Sopenharmony_ci enum quirk which, 275a46c0ec8Sopenharmony_ci bool *val); 276a46c0ec8Sopenharmony_ci 277a46c0ec8Sopenharmony_ci/** 278a46c0ec8Sopenharmony_ci * Get the value of the given quirk, as dimension. 279a46c0ec8Sopenharmony_ci * This function will assert if the quirk type does not match the 280a46c0ec8Sopenharmony_ci * requested type. If the quirk is not set for this device, val is 281a46c0ec8Sopenharmony_ci * unchanged. 282a46c0ec8Sopenharmony_ci * 283a46c0ec8Sopenharmony_ci * @return true if the quirk value is valid, false otherwise. 284a46c0ec8Sopenharmony_ci */ 285a46c0ec8Sopenharmony_cibool 286a46c0ec8Sopenharmony_ciquirks_get_dimensions(struct quirks *q, 287a46c0ec8Sopenharmony_ci enum quirk which, 288a46c0ec8Sopenharmony_ci struct quirk_dimensions *val); 289a46c0ec8Sopenharmony_ci 290a46c0ec8Sopenharmony_ci/** 291a46c0ec8Sopenharmony_ci * Get the value of the given quirk, as range. 292a46c0ec8Sopenharmony_ci * This function will assert if the quirk type does not match the 293a46c0ec8Sopenharmony_ci * requested type. If the quirk is not set for this device, val is 294a46c0ec8Sopenharmony_ci * unchanged. 295a46c0ec8Sopenharmony_ci * 296a46c0ec8Sopenharmony_ci * @return true if the quirk value is valid, false otherwise. 297a46c0ec8Sopenharmony_ci */ 298a46c0ec8Sopenharmony_cibool 299a46c0ec8Sopenharmony_ciquirks_get_range(struct quirks *q, 300a46c0ec8Sopenharmony_ci enum quirk which, 301a46c0ec8Sopenharmony_ci struct quirk_range *val); 302a46c0ec8Sopenharmony_ci 303a46c0ec8Sopenharmony_ci/** 304a46c0ec8Sopenharmony_ci * Get the tuples of the given quirk. 305a46c0ec8Sopenharmony_ci * This function will assert if the quirk type does not match the 306a46c0ec8Sopenharmony_ci * requested type. If the quirk is not set for this device, tuples is 307a46c0ec8Sopenharmony_ci * unchanged. 308a46c0ec8Sopenharmony_ci * 309a46c0ec8Sopenharmony_ci * @return true if the quirk value is valid, false otherwise. 310a46c0ec8Sopenharmony_ci */ 311a46c0ec8Sopenharmony_cibool 312a46c0ec8Sopenharmony_ciquirks_get_tuples(struct quirks *q, 313a46c0ec8Sopenharmony_ci enum quirk which, 314a46c0ec8Sopenharmony_ci const struct quirk_tuples **tuples); 315a46c0ec8Sopenharmony_ci 316a46c0ec8Sopenharmony_ci/** 317a46c0ec8Sopenharmony_ci * Get the uint32 array of the given quirk. 318a46c0ec8Sopenharmony_ci * This function will assert if the quirk type does not match the 319a46c0ec8Sopenharmony_ci * requested type. If the quirk is not set for this device, tuples is 320a46c0ec8Sopenharmony_ci * unchanged. 321a46c0ec8Sopenharmony_ci * 322a46c0ec8Sopenharmony_ci * @return true if the quirk value is valid, false otherwise. 323a46c0ec8Sopenharmony_ci */ 324a46c0ec8Sopenharmony_cibool 325a46c0ec8Sopenharmony_ciquirks_get_uint32_array(struct quirks *q, 326a46c0ec8Sopenharmony_ci enum quirk which, 327a46c0ec8Sopenharmony_ci const uint32_t **array, 328a46c0ec8Sopenharmony_ci size_t *nelements); 329