Hi Christopher,
On Wed, Dec 21, 2011 at 06:10:01PM -0800, Christopher Heiny wrote:Signed-off-by: Christopher Heiny<cheiny@xxxxxxxxxxxxx>
A bunch of comments generally applicable to all patches.
I have not looked at the core thoroughly yet.
---
drivers/input/rmi4/rmi_f19.c | 1571 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1571 insertions(+), 0 deletions(-)
diff --git a/drivers/input/rmi4/rmi_f19.c b/drivers/input/rmi4/rmi_f19.c
new file mode 100644
index 0000000..a678f30
--- /dev/null
+++ b/drivers/input/rmi4/rmi_f19.c
@@ -0,0 +1,1571 @@
+/*
+
+struct f19_0d_control_0 {
+ union {
+ struct {
+ u8 button_usage:2;
+ u8 filter_mode:2;
+ };
+ u8 f19_0d_control0;
+ };
Anonymous union in a struct is kind of pointless...
+};
+
+struct f19_0d_control_1 {
+ u8 int_enabled_button;
+};
+
+struct f19_0d_control_2 {
+ u8 single_button;
+};
+
+struct f19_0d_control_3_4 {
+ u8 sensor_map_button:7;
+ /*u8 sensitivity_button;*/
+};
+
+struct f19_0d_control_5 {
+ u8 sensitivity_adj;
+};
+struct f19_0d_control_6 {
+ u8 hysteresis_threshold;
+};
+
+struct f19_0d_control {
+ struct f19_0d_control_0 *general_control;
Single instance, does not need to be allocated separately.
+ struct f19_0d_control_1 *button_int_enable;
+ struct f19_0d_control_2 *single_button_participation;
+ struct f19_0d_control_3_4 *sensor_map;
This should probably be an array of
struct f19_button_ctrl {
struct f19_0d_control_1 int_enable;
struct f19_0d_control_2 participation;
struct f19_0d_control_3_4 sensor_map;
};
located at the end of f19_0d_control structure so it can be all
allocated in one shot.
+ struct f19_0d_control_5 *all_button_sensitivity_adj;
Single instance, does not need to be allocated separately.
+ struct f19_0d_control_6 *all_button_hysteresis_threshold;
Single instance, does not need to be allocated separately.
+};
+/* data specific to fn $19 that needs to be kept around */
+struct f19_data {
+ struct f19_0d_control *button_control;
+ struct f19_0d_query button_query;
+ u8 button_rezero;
+ bool *button_down;
Just let input core track this for you.
+ unsigned char button_count;
+ unsigned char button_data_buffer_size;
Your fingers must be hurting by the time you finished writing this
driver...
+ unsigned char *button_data_buffer;
+ unsigned char *button_map;
Linux keycodes are wider than 8 bits, should be unsigned short.
+ char input_name[MAX_LEN];
+ char input_phys[MAX_LEN];
+ struct input_dev *input;
+};
+
+static ssize_t rmi_f19_button_count_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+
+static ssize_t rmi_f19_button_map_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f19_button_map_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+static ssize_t rmi_f19_rezero_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+static ssize_t rmi_f19_rezero_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+static ssize_t rmi_f19_has_hysteresis_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t rmi_f19_has_sensitivity_adjust_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t rmi_f19_configurable_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t rmi_f19_filter_mode_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+static ssize_t rmi_f19_filter_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+static ssize_t rmi_f19_button_usage_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+static ssize_t rmi_f19_button_usage_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+static ssize_t rmi_f19_interrupt_enable_button_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+static ssize_t rmi_f19_interrupt_enable_button_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+static ssize_t rmi_f19_single_button_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+static ssize_t rmi_f19_single_button_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+static ssize_t rmi_f19_sensor_map_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+static ssize_t rmi_f19_sensor_map_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+static ssize_t rmi_f19_sensitivity_adjust_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+static ssize_t rmi_f19_sensitivity_adjust_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+static ssize_t rmi_f19_hysteresis_threshold_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+static ssize_t rmi_f19_hysteresis_threshold_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+
+
+static inline int rmi_f19_alloc_memory(struct rmi_function_container *fc);
+
+static inline void rmi_f19_free_memory(struct rmi_function_container *fc);
+
+static inline int rmi_f19_initialize(struct rmi_function_container *fc);
+
+static inline int rmi_f19_register_device(struct rmi_function_container *fc);
+
+static inline int rmi_f19_create_sysfs(struct rmi_function_container *fc);
+
+static int rmi_f19_config(struct rmi_function_container *fc);
+
+static int rmi_f19_reset(struct rmi_function_container *fc);
+
+static struct device_attribute attrs[] = {
+ __ATTR(button_count, RMI_RO_ATTR,
+ rmi_f19_button_count_show, rmi_store_error),
Why not NULL instead of rmi_store_error?
+ __ATTR(button_map, RMI_RW_ATTR,
+ rmi_f19_button_map_show, rmi_f19_button_map_store),
+ __ATTR(rezero, RMI_RW_ATTR,
+ rmi_f19_rezero_show, rmi_f19_rezero_store),
+ __ATTR(has_hysteresis_threshold, RMI_RO_ATTR,
+ rmi_f19_has_hysteresis_threshold_show, rmi_store_error),
+ __ATTR(has_sensitivity_adjust, RMI_RO_ATTR,
+ rmi_f19_has_sensitivity_adjust_show, rmi_store_error),
+ __ATTR(configurable, RMI_RO_ATTR,
+ rmi_f19_configurable_show, rmi_store_error),
+ __ATTR(filter_mode, RMI_RW_ATTR,
+ rmi_f19_filter_mode_show, rmi_f19_filter_mode_store),
+ __ATTR(button_usage, RMI_RW_ATTR,
+ rmi_f19_button_usage_show, rmi_f19_button_usage_store),
+ __ATTR(interrupt_enable_button, RMI_RW_ATTR,
+ rmi_f19_interrupt_enable_button_show,
+ rmi_f19_interrupt_enable_button_store),
+ __ATTR(single_button, RMI_RW_ATTR,
+ rmi_f19_single_button_show, rmi_f19_single_button_store),
+ __ATTR(sensor_map, RMI_RW_ATTR,
+ rmi_f19_sensor_map_show, rmi_f19_sensor_map_store),
+ __ATTR(sensitivity_adjust, RMI_RW_ATTR,
+ rmi_f19_sensitivity_adjust_show,
+ rmi_f19_sensitivity_adjust_store),
+ __ATTR(hysteresis_threshold, RMI_RW_ATTR,
+ rmi_f19_hysteresis_threshold_show,
+ rmi_f19_hysteresis_threshold_store)
+};
+
+
+int rmi_f19_read_control_parameters(struct rmi_device *rmi_dev,
+ struct f19_0d_control *button_control,
+ unsigned char button_count,
+ unsigned char int_button_enabled_count,
+ u8 ctrl_base_addr)
+{
+ int error = 0;
+ int i;
+
+ if (button_control->general_control) {
It can't be NULL.
+ error = rmi_read_block(rmi_dev, ctrl_base_addr,
+ (u8 *)button_control->general_control,
+ sizeof(struct f19_0d_control_0));
+ if (error< 0) {
+ dev_err(&rmi_dev->dev,
+ "Failed to read f19_0d_control_0, code:"
+ " %d.\n", error);
+ return error;
+ }
+ ctrl_base_addr = ctrl_base_addr +
+ sizeof(struct f19_0d_control_0);
+ }
+
+ if (button_control->button_int_enable) {
Neither can this.
+ for (i = 0; i< int_button_enabled_count; i++) {
+ error = rmi_read_block(rmi_dev, ctrl_base_addr,
+ (u8 *)&button_control->button_int_enable[i],
+ sizeof(struct f19_0d_control_1));
+ if (error< 0) {
+ dev_err(&rmi_dev->dev,
+ "Failed to read f19_0d_control_2,"
+ " code: %d.\n", error);
+ return error;
+ }
+ ctrl_base_addr = ctrl_base_addr +
+ sizeof(struct f19_0d_control_1);
+ }
+ }
+
+ if (button_control->single_button_participation) {
Nor this.
+ for (i = 0; i< int_button_enabled_count; i++) {
+ error = rmi_read_block(rmi_dev, ctrl_base_addr,
+ (u8 *)&button_control->
+ single_button_participation[i],
+ sizeof(struct f19_0d_control_2));
+ if (error< 0) {
+ dev_err(&rmi_dev->dev,
+ "Failed to read f19_0d_control_2,"
+ " code: %d.\n", error);
+ return error;
+ }
+ ctrl_base_addr = ctrl_base_addr +
+ sizeof(struct f19_0d_control_2);
+ }
+ }
+
+ if (button_control->sensor_map) {
Nor this...
+ for (i = 0; i< button_count; i++) {
+ error = rmi_read_block(rmi_dev, ctrl_base_addr,
+ (u8 *)&button_control->sensor_map[i],
+ sizeof(struct f19_0d_control_3_4));
+ if (error< 0) {
+ dev_err(&rmi_dev->dev,
+ "Failed to read f19_0d_control_3_4,"
+ " code: %d.\n", error);
+ return error;
+ }
+ ctrl_base_addr = ctrl_base_addr +
+ sizeof(struct f19_0d_control_3_4);
+ }
+ }
+
+ if (button_control->all_button_sensitivity_adj) {
Nor this.
+ error = rmi_read_block(rmi_dev, ctrl_base_addr,
+ (u8 *)button_control->
+ all_button_sensitivity_adj,
+ sizeof(struct f19_0d_control_5));
+ if (error< 0) {
+ dev_err(&rmi_dev->dev,
+ "Failed to read f19_0d_control_5,"
+ " code: %d.\n", error);
+ return error;
+ }
+ ctrl_base_addr = ctrl_base_addr +
+ sizeof(struct f19_0d_control_5);
+ }
+
+ if (button_control->all_button_hysteresis_threshold) {
...
+ error = rmi_read_block(rmi_dev, ctrl_base_addr,
+ (u8 *)button_control->
+ all_button_hysteresis_threshold,
+ sizeof(struct f19_0d_control_6));
+ if (error< 0) {
+ dev_err(&rmi_dev->dev,
+ "Failed to read f19_0d_control_6,"
+ " code: %d.\n", error);
+ return error;
+ }
+ ctrl_base_addr = ctrl_base_addr +
+ sizeof(struct f19_0d_control_6);
+ }
+ return 0;
+}
+
+
+static inline int rmi_f19_alloc_memory(struct rmi_function_container *fc)
Please drop inline throughout, let compiler do its job.
+
+ f19->button_data_buffer_size = (f19->button_count + 7) / 8;
DIV_ROUND_UP(f19->button_count, 8);
+ f19->button_data_buffer =
+ kcalloc(f19->button_data_buffer_size,
+ sizeof(unsigned char), GFP_KERNEL);
+ if (!f19->button_data_buffer) {
+ dev_err(&fc->dev, "Failed to allocate button data buffer.\n");
+ return -ENOMEM;
+ }
+
+ f19->button_map = kcalloc(f19->button_count,
+ sizeof(unsigned char), GFP_KERNEL);
+ if (!f19->button_map) {
+ dev_err(&fc->dev, "Failed to allocate button map.\n");
+ return -ENOMEM;
+ }
+
+ f19->button_control = kzalloc(sizeof(struct f19_0d_control),
+ GFP_KERNEL);
If you allocate a single copy of this structure why isn't it a member of
struct f19_data to begin with?
+ if (!f19->button_control) {
+ dev_err(&fc->dev, "Failed to allocate button_control.\n");
+ return -ENOMEM;
+ }
+
+ f19->button_control->general_control =
+ kzalloc(sizeof(struct f19_0d_control_0), GFP_KERNEL);
This a single byte, why do you need to allocate it separately?
+ if (!f19->button_control->general_control) {
+ dev_err(&fc->dev, "Failed to allocate"
+ " f19_0d_control_0.\n");
+ return -ENOMEM;
+ }
+
+ f19->button_control->button_int_enable =
+ kzalloc(f19->button_data_buffer_size *
+ sizeof(struct f19_0d_control_2), GFP_KERNEL);
+ if (!f19->button_control->button_int_enable) {
+ dev_err(&fc->dev, "Failed to allocate f19_0d_control_1.\n");
+ return -ENOMEM;
+ }
+
+ f19->button_control->single_button_participation =
+ kzalloc(f19->button_data_buffer_size *
+ sizeof(struct f19_0d_control_2), GFP_KERNEL);
+ if (!f19->button_control->single_button_participation) {
+ dev_err(&fc->dev, "Failed to allocate"
+ " f19_0d_control_2.\n");
Do not split error messages; it's OK if they exceed 80 column limit.
+ return -ENOMEM;
+ }
+
+ f19->button_control->sensor_map =
+ kzalloc(f19->button_count *
+ sizeof(struct f19_0d_control_3_4), GFP_KERNEL);
+ if (!f19->button_control->sensor_map) {
+ dev_err(&fc->dev, "Failed to allocate"
+ " f19_0d_control_3_4.\n");
+ return -ENOMEM;
+ }
+
+ f19->button_control->all_button_sensitivity_adj =
+ kzalloc(sizeof(struct f19_0d_control_5), GFP_KERNEL);
+ if (!f19->button_control->all_button_sensitivity_adj) {
+ dev_err(&fc->dev, "Failed to allocate"
+ " f19_0d_control_5.\n");
+ return -ENOMEM;
+ }
+
+ f19->button_control->all_button_hysteresis_threshold =
+ kzalloc(sizeof(struct f19_0d_control_6), GFP_KERNEL);
+ if (!f19->button_control->all_button_hysteresis_threshold) {
+ dev_err(&fc->dev, "Failed to allocate"
+ " f19_0d_control_6.\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+
+
+static inline void rmi_f19_free_memory(struct rmi_function_container *fc)
+{
+ struct f19_data *f19 = fc->data;
+
+ if (f19) {
Can it be NULL? How?
+ kfree(f19->button_down);
+ kfree(f19->button_data_buffer);
+ kfree(f19->button_map);
+ if (f19->button_control) {
+ kfree(f19->button_control->general_control);
+ kfree(f19->button_control->button_int_enable);
+ kfree(f19->button_control->single_button_participation);
+ kfree(f19->button_control->sensor_map);
+ kfree(f19->button_control->all_button_sensitivity_adj);
+ kfree(f19->button_control->
+ all_button_hysteresis_threshold);
+ kfree(f19->button_control);
+ }
+ kfree(f19);
+ fc->data = NULL;
+ }
+}
+
+
+static inline int rmi_f19_initialize(struct rmi_function_container *fc)
+{
+ struct rmi_device *rmi_dev = fc->rmi_dev;
+ struct rmi_device_platform_data *pdata;
+ struct f19_data *f19 = fc->data;
+ int i;
+ int rc;
+
+ dev_info(&fc->dev, "Intializing F19 values.");
dev_dbg()
+
+ /* initial all default values for f19 data here */
+ rc = rmi_read(rmi_dev, fc->fd.command_base_addr,
+ (u8 *)&f19->button_rezero);
+ if (rc< 0) {
+ dev_err(&fc->dev, "Failed to read command register.\n");
+ return rc;
+ }
+ f19->button_rezero = f19->button_rezero& 1;
+
+static inline int rmi_f19_register_device(struct rmi_function_container *fc)
+{
+ struct rmi_device *rmi_dev = fc->rmi_dev;
+ struct input_dev *input_dev;
+ struct f19_data *f19 = fc->data;
+ int i;
+ int rc;
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ dev_err(&fc->dev, "Failed to allocate input device.\n");
+ return -ENOMEM;
+ }
+
+ f19->input = input_dev;
+ snprintf(f19->input_name, MAX_LEN, "%sfn%02x", dev_name(&rmi_dev->dev),
+ fc->fd.function_number);
+ input_dev->name = f19->input_name;
+ snprintf(f19->input_phys, MAX_LEN, "%s/input0", input_dev->name);
+ input_dev->phys = f19->input_phys;
+ input_dev->dev.parent =&rmi_dev->dev;
+ input_set_drvdata(input_dev, f19);
+
+ /* Set up any input events. */
+ set_bit(EV_SYN, input_dev->evbit);
+ set_bit(EV_KEY, input_dev->evbit);
__set_bit(), no need to lock the bus.
+ /* set bits for each button... */
+ for (i = 0; i< f19->button_count; i++)
+ set_bit(f19->button_map[i], input_dev->keybit);
+ rc = input_register_device(input_dev);
+ if (rc< 0) {
+ dev_err(&fc->dev, "Failed to register input device.\n");
+ goto error_free_device;
+ }
+
+ return 0;
+static inline int rmi_f19_create_sysfs(struct rmi_function_container *fc)
+{
+ int attr_count = 0;
+ int rc;
+
+ dev_dbg(&fc->dev, "Creating sysfs files.\n");
+ /* Set up sysfs device attributes. */
+ for (attr_count = 0; attr_count< ARRAY_SIZE(attrs); attr_count++) {
+ if (sysfs_create_file
+ (&fc->dev.kobj,&attrs[attr_count].attr)< 0) {
+ dev_err(&fc->dev,
+ "Failed to create sysfs file for %s.",
+ attrs[attr_count].attr.name);
+ rc = -ENODEV;
+ goto err_remove_sysfs;
+ }
+ }
This is called attribute group, please use it.
+
+ return 0;
+
+err_remove_sysfs:
+ for (attr_count--; attr_count>= 0; attr_count--)
+ sysfs_remove_file(&fc->dev.kobj,
+ &attrs[attr_count].attr);
+ return rc;
+
+}
+
+
+
+static int rmi_f19_config(struct rmi_function_container *fc)
+{
+ struct f19_data *data;
+ int retval;
+ int ctrl_base_addr;
+ int button_reg;
+
+ data = fc->data;
+
+ ctrl_base_addr = fc->fd.control_base_addr;
+
+ button_reg = (data->button_count / 7) + 1;
Please combine variable declarations and initializations - this makes
code a bit less verbose and easier to read.
+
+int rmi_f19_attention(struct rmi_function_container *fc, u8 *irq_bits)
static.
+{
+ struct rmi_device *rmi_dev = fc->rmi_dev;
+ struct f19_data *f19 = fc->data;
+ u8 data_base_addr = fc->fd.data_base_addr;
+ int error;
+ int button;
+
+ /* Read the button data. */
+
+ error = rmi_read_block(rmi_dev, data_base_addr, f19->button_data_buffer,
+ f19->button_data_buffer_size);
+ if (error< 0) {
+ dev_err(&fc->dev, "%s: Failed to read button data registers.\n",
+ __func__);
+ return error;
+ }
+
+ /* Generate events for buttons that change state. */
+ for (button = 0; button< f19->button_count;
+ button++) {
+ int button_reg;
+ int button_shift;
+ bool button_status;
+
+ /* determine which data byte the button status is in */
+ button_reg = button / 7;
+ /* bit shift to get button's status */
+ button_shift = button % 8;
+ button_status =
+ ((f19->button_data_buffer[button_reg]>> button_shift)
+ & 0x01) != 0;
+
+ /* if the button state changed from the last time report it
+ * and store the new state */
+ if (button_status != f19->button_down[button]) {
+ dev_dbg(&fc->dev, "%s: Button %d (code %d) -> %d.\n",
+ __func__, button, f19->button_map[button],
+ button_status);
+ /* Generate an event here. */
+ input_report_key(f19->input, f19->button_map[button],
+ button_status);
+ f19->button_down[button] = button_status;
+ }
+ }
All of the above could be reduced to:
for (button = 0; button< f19->button_count; button++)
input_report_key(f19->input, f19->button_map[button],
test_bit(button, f19->button_data_buffer);
+
+static ssize_t rmi_f19_sensor_map_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct rmi_function_container *fc;
+ struct f19_data *data;
+ int sensor_map;
+ int i;
+ int retval = count;
+ int button_count = 0;
+ int ctrl_bass_addr;
+ int button_reg;
+ fc = to_rmi_function_container(dev);
+ data = fc->data;
+
+ if (data->button_query.configurable == 0) {
+ dev_err(dev,
+ "%s: Error - sensor map is not configuralbe at"
+ " run-time", __func__);
This is not driver error, return error silently.
+ return -EINVAL;
+ }
If sensor is not cinfigurable maybe attributes mode should be adjusted
to be read-only?
+
+static ssize_t rmi_f19_button_map_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct rmi_function_container *fc;
+ struct f19_data *data;
+ unsigned int button;
+ int i;
+ int retval = count;
+ int button_count = 0;
+ unsigned char temp_button_map[KEY_MAX];
+
+ fc = to_rmi_function_container(dev);
+ data = fc->data;
+
+ /* Do validation on the button map data passed in. Store button
+ * mappings into a temp buffer and then verify button count and
+ * data prior to clearing out old button mappings and storing the
+ * new ones. */
+ for (i = 0; i< data->button_count&& *buf != 0;
+ i++) {
+ /* get next button mapping value and store and bump up to
+ * point to next item in buf */
+ sscanf(buf, "%u",&button);
+
+ /* Make sure the key is a valid key */
+ if (button> KEY_MAX) {
+ dev_err(dev,
+ "%s: Error - button map for button %d is not a"
+ " valid value 0x%x.\n", __func__, i, button);
+ retval = -EINVAL;
+ goto err_ret;
+ }
+
+ temp_button_map[i] = button;
+ button_count++;
+
+ /* bump up buf to point to next item to read */
+ while (*buf != 0) {
+ buf++;
+ if (*(buf - 1) == ' ')
+ break;
+ }
+ }
+
+ /* Make sure the button count matches */
+ if (button_count != data->button_count) {
+ dev_err(dev,
+ "%s: Error - button map count of %d doesn't match device "
+ "button count of %d.\n", __func__, button_count,
+ data->button_count);
+ retval = -EINVAL;
+ goto err_ret;
+ }
+
+ /* Clear the key bits for the old button map. */
+ for (i = 0; i< button_count; i++)
+ clear_bit(data->button_map[i], data->input->keybit);
+
+ /* Switch to the new map. */
+ memcpy(data->button_map, temp_button_map,
+ data->button_count);
+
+ /* Loop through the key map and set the key bit for the new mapping. */
+ for (i = 0; i< button_count; i++)
+ set_bit(data->button_map[i], data->input->keybit);
+
+err_ret:
+ return retval;
+}
Button map (keymap) should be manipulated with EVIOCGKEYCODE and
EVIOCSKEYCODE ioctls, no need to invent driver-specific way of doing
this.