^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Helpers for matrix keyboard bindings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2012 Google, Inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Olof Johansson <olof@lixom.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/input/matrix_keypad.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static bool matrix_keypad_map_key(struct input_dev *input_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) unsigned int rows, unsigned int cols,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) unsigned int row_shift, unsigned int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned short *keymap = input_dev->keycode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned int row = KEY_ROW(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned int col = KEY_COL(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned short code = KEY_VAL(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (row >= rows || col >= cols) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) dev_err(input_dev->dev.parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) "%s: invalid keymap entry 0x%x (row: %d, col: %d, rows: %d, cols: %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) __func__, key, row, col, rows, cols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) keymap[MATRIX_SCAN_CODE(row, col, row_shift)] = code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) __set_bit(code, input_dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * matrix_keypad_parse_properties() - Read properties of matrix keypad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * @dev: Device containing properties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * @rows: Returns number of matrix rows
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * @cols: Returns number of matrix columns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * @return 0 if OK, <0 on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) int matrix_keypad_parse_properties(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) unsigned int *rows, unsigned int *cols)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) *rows = *cols = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) device_property_read_u32(dev, "keypad,num-rows", rows);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) device_property_read_u32(dev, "keypad,num-columns", cols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (!*rows || !*cols) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) dev_err(dev, "number of keypad rows/columns not specified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) EXPORT_SYMBOL_GPL(matrix_keypad_parse_properties);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static int matrix_keypad_parse_keymap(const char *propname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) unsigned int rows, unsigned int cols,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct input_dev *input_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct device *dev = input_dev->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned int row_shift = get_count_order(cols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned int max_keys = rows << row_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u32 *keys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (!propname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) propname = "linux,keymap";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) size = device_property_count_u32(dev, propname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (size <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) dev_err(dev, "missing or malformed property %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) propname, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return size < 0 ? size : -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (size > max_keys) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) dev_err(dev, "%s size overflow (%d vs max %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) propname, size, max_keys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) keys = kmalloc_array(size, sizeof(u32), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (!keys)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) retval = device_property_read_u32_array(dev, propname, keys, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dev_err(dev, "failed to read %s property: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) propname, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) for (i = 0; i < size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (!matrix_keypad_map_key(input_dev, rows, cols,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) row_shift, keys[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) kfree(keys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * matrix_keypad_build_keymap - convert platform keymap into matrix keymap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * @keymap_data: keymap supplied by the platform code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * @keymap_name: name of device tree property containing keymap (if device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * tree support is enabled).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * @rows: number of rows in target keymap array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * @cols: number of cols in target keymap array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * @keymap: expanded version of keymap that is suitable for use by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * matrix keyboard driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * @input_dev: input devices for which we are setting up the keymap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * This function converts platform keymap (encoded with KEY() macro) into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * an array of keycodes that is suitable for using in a standard matrix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * keyboard driver that uses row and col as indices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * If @keymap_data is not supplied and device tree support is enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * it will attempt load the keymap from property specified by @keymap_name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * argument (or "linux,keymap" if @keymap_name is %NULL).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * If @keymap is %NULL the function will automatically allocate managed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * block of memory to store the keymap. This memory will be associated with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * the parent device and automatically freed when device unbinds from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * Callers are expected to set up input_dev->dev.parent before calling this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) const char *keymap_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) unsigned int rows, unsigned int cols,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) unsigned short *keymap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct input_dev *input_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) unsigned int row_shift = get_count_order(cols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) size_t max_keys = rows << row_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (WARN_ON(!input_dev->dev.parent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (!keymap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) keymap = devm_kcalloc(input_dev->dev.parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) max_keys, sizeof(*keymap),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (!keymap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) dev_err(input_dev->dev.parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) "Unable to allocate memory for keymap");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) input_dev->keycode = keymap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) input_dev->keycodesize = sizeof(*keymap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) input_dev->keycodemax = max_keys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) __set_bit(EV_KEY, input_dev->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (keymap_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) for (i = 0; i < keymap_data->keymap_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) unsigned int key = keymap_data->keymap[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (!matrix_keypad_map_key(input_dev, rows, cols,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) row_shift, key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) error = matrix_keypad_parse_keymap(keymap_name, rows, cols,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) __clear_bit(KEY_RESERVED, input_dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) EXPORT_SYMBOL(matrix_keypad_build_keymap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) MODULE_LICENSE("GPL");