* [PATCH v2 13/14] input: cyapa: add gen5 trackpad device read firmware image and raw data functions supported
From: Dudley Du @ 2014-06-30 6:44 UTC (permalink / raw)
To: Alan Stern, Dmitry Torokhov, patrikf@google.com,
Rafael J. Wysocki
Cc: Benson Leung, Daniel Kurtz, linux-input@vger.kernel.org,
linux-kernel@vger.kernel.org
Add read firmware image function supported for gen5 trackpad device,
which its function is supplied through cyapa core read_fw interface.
Through this interface, upper layer application can read out, check
and backup the firmware image in trackpad device before updated
with new one when new firmware image may have problems.
Also add interfaces to report all sensor's raw data values to upper
layer, so it can help to find out the performance issue when users
reports problem, and also it's useful and required interface for
some customers that require sensors' raw data.
TEST=test on Chomebooks.
Signed-off-by: Du, Dudley <dudl@cypress.com>
---
diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c
index 3da6a91..817842e 100644
--- a/drivers/input/mouse/cyapa_gen5.c
+++ b/drivers/input/mouse/cyapa_gen5.c
@@ -1159,6 +1159,158 @@ static int cyapa_gen5_write_fw_block(struct cyapa *cyapa,
return 0;
}
+static int cyapa_gen5_read_fw_bytes(struct cyapa *cyapa, u16 row_num, u8 *data)
+{
+ int ret;
+ u8 cmd[16];
+ size_t cmd_len;
+ u8 resp_data[CYAPA_TSG_FW_ROW_SIZE / 2 + GEN5_MIN_BL_RESP_LENGTH];
+ int resp_len;
+ u16 offset;
+ u16 cmd_crc;
+ struct cyapa_tsg_bin_image_data_record *fw_img_record;
+
+ fw_img_record = (struct cyapa_tsg_bin_image_data_record *)data;
+
+ cmd[0] = 0x04; /* register address */
+ cmd[1] = 0x00;
+ cmd[2] = 0x0e;
+ cmd[3] = 0x00;
+ cmd[4] = 0x40; /* report id 40h */
+ cmd[5] = 0x00;
+ cmd[6] = GEN5_SOP_KEY;
+ cmd[7] = 0x3d; /* read application image command code */
+ cmd[8] = 0x03;
+ cmd[9] = 0x00;
+ offset = row_num * CYAPA_TSG_FW_ROW_SIZE -
+ CYAPA_TSG_START_OF_APPLICATION;
+ put_unaligned_le16(offset, &cmd[10]);
+ cmd[12] = CYAPA_TSG_IMG_READ_SIZE;
+ cmd_crc = crc_itu_t(0xffff, &cmd[6], 7);
+ put_unaligned_le16(cmd_crc, &cmd[13]); /* CRC[15:0] */
+ cmd[15] = GEN5_EOP_KEY; /* EOP = 17h */
+ cmd_len = 16;
+
+ resp_len = CYAPA_TSG_IMG_READ_SIZE + GEN5_MIN_BL_RESP_LENGTH;
+ ret = cyapa_i2c_pip_cmd_irq_sync(cyapa,
+ cmd, cmd_len,
+ resp_data, &resp_len,
+ 50, cyapa_gen5_sort_tsg_pip_bl_resp_data);
+ if (resp_len != (CYAPA_TSG_IMG_READ_SIZE + GEN5_MIN_BL_RESP_LENGTH) ||
+ ret || resp_data[2] != GEN5_BL_RESP_REPORT_ID ||
+ !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]))
+ return (ret < 0) ? ret : -EAGAIN;
+
+ /* copy first 64 bytes in the row. */
+ memcpy(&fw_img_record->record_data[0], &resp_data[8],
+ CYAPA_TSG_IMG_READ_SIZE);
+
+ if (row_num == CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM) {
+ /* last row's rest 64 bytes are bootloader metadata,
+ * it's not allowed to be read out, will respond with error. */
+ memset(&fw_img_record->record_data[CYAPA_TSG_IMG_READ_SIZE],
+ 0, CYAPA_TSG_IMG_READ_SIZE);
+ goto skip_last_row;
+ }
+
+ /* read next 64 bytes in the row. */
+ offset = offset + CYAPA_TSG_IMG_READ_SIZE;
+ put_unaligned_le16(offset, &cmd[10]);
+ cmd_crc = crc_itu_t(0xffff, &cmd[6], 7);
+ put_unaligned_le16(cmd_crc, &cmd[13]); /* CRC[15:0] */
+ ret = cyapa_i2c_pip_cmd_irq_sync(cyapa,
+ cmd, cmd_len,
+ resp_data, &resp_len,
+ 500, cyapa_gen5_sort_tsg_pip_bl_resp_data);
+ if (resp_len != (CYAPA_TSG_IMG_READ_SIZE + GEN5_MIN_BL_RESP_LENGTH) ||
+ ret || resp_data[2] != GEN5_BL_RESP_REPORT_ID ||
+ !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]))
+ return (ret < 0) ? ret : -EAGAIN;
+
+ /* copy last 64 bytes in the row. */
+ memcpy(&fw_img_record->record_data[CYAPA_TSG_IMG_READ_SIZE],
+ &resp_data[8], CYAPA_TSG_IMG_READ_SIZE);
+
+skip_last_row:
+ fw_img_record->flash_array_id = 0;
+ put_unaligned_be16(row_num, &fw_img_record->row_number);
+ put_unaligned_be16(CYAPA_TSG_FW_ROW_SIZE, &fw_img_record->record_len);
+
+ return 0;
+}
+
+static int cyapa_gen5_read_fw(struct cyapa *cyapa)
+{
+ int ret;
+ int fw_img_head_size;
+ int fw_img_record_size;
+ int row_index;
+ int array_index;
+ u32 img_start;
+ u16 img_len;
+ u16 img_start_row;
+ u16 img_end_row;
+ struct cyapa_tsg_bin_image_data_record app_integrity;
+ u8 *record_data;
+
+ ret = cyapa_gen5_bl_enter(cyapa);
+ if (ret)
+ goto err;
+
+ cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
+
+ fw_img_head_size = sizeof(struct cyapa_tsg_bin_image_head);
+ fw_img_record_size = sizeof(struct cyapa_tsg_bin_image_data_record);
+
+ /* Read app integrity block data. */
+ row_index = CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM;
+ ret = cyapa_gen5_read_fw_bytes(cyapa, row_index, (u8 *)&app_integrity);
+ if (ret)
+ goto err;
+ img_start = get_unaligned_le32(&app_integrity.record_data[16]);
+ img_len = get_unaligned_le16(&app_integrity.record_data[20]);
+ if ((img_start + img_len) % CYAPA_TSG_FW_ROW_SIZE)
+ goto err;
+ img_start_row = img_start / CYAPA_TSG_FW_ROW_SIZE;
+ img_end_row = (img_start + img_len) / CYAPA_TSG_FW_ROW_SIZE - 1;
+
+ /* allocate memory for image. */
+ cyapa->read_fw_image_size = fw_img_head_size +
+ (img_end_row - img_start_row + 2) * fw_img_record_size;
+ cyapa->read_fw_image = kmalloc(cyapa->read_fw_image_size, GFP_KERNEL);
+ if (!cyapa->read_fw_image) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /* set image head data. */
+ memcpy(cyapa->read_fw_image, &gen5_fw_img_head, fw_img_head_size);
+
+ /* read image blocks. */
+ for (row_index = img_start_row, array_index = 0;
+ row_index <= img_end_row;
+ row_index++, array_index++) {
+ record_data = &cyapa->read_fw_image[fw_img_head_size +
+ array_index * fw_img_record_size];
+ ret = cyapa_gen5_read_fw_bytes(cyapa, row_index, record_data);
+ if (ret)
+ goto err;
+ }
+
+ /* append last app integrity block data. */
+ record_data = &cyapa->read_fw_image[fw_img_head_size +
+ array_index * fw_img_record_size];
+ memcpy(record_data, &app_integrity, fw_img_record_size);
+
+err:
+ if (ret) {
+ kfree(cyapa->read_fw_image);
+ cyapa->read_fw_image = NULL;
+ cyapa->read_fw_image_size = 0;
+ }
+ return ret;
+}
+
static int cyapa_gen5_do_fw_update(struct cyapa *cyapa,
const struct firmware *fw)
{
@@ -2152,6 +2304,109 @@ resume_scanning:
return ret + err;
}
+static int cyapa_gen5_read_raw_data(struct cyapa *cyapa)
+{
+ int ret, err;
+ int raw_cap_mutual_max, raw_cap_mutual_min, raw_cap_mutual_ave;
+ int raw_cap_self_max, raw_cap_self_min, raw_cap_self_ave;
+ int offset;
+ int data_size, max, min, ave;
+ ktime_t time_mono;
+
+ offset = 0;
+ if (!cyapa->tp_raw_data) {
+ if (cyapa->state != CYAPA_STATE_GEN5_APP ||
+ !cyapa->electrodes_x || !cyapa->electrodes_y)
+ return -EINVAL;
+
+ cyapa->tp_raw_data_size = sizeof(s32) * (cyapa->electrodes_x *
+ cyapa->electrodes_y + cyapa->electrodes_x +
+ cyapa->electrodes_y) + GEN5_RAW_DATA_HEAD_SIZE;
+ /* This buffer will be hold after used until the driver is
+ * unloaded, the purpose of it is to improve the performace
+ * to avoid frequently allocate and release the buffer. */
+ cyapa->tp_raw_data =
+ kmalloc(cyapa->tp_raw_data_size, GFP_KERNEL);
+ if (!cyapa->tp_raw_data)
+ return -ENOMEM;
+ memset(cyapa->tp_raw_data, 0, cyapa->tp_raw_data_size);
+ }
+
+
+ /* 1. suspend Scanning.
+ * After suspend scanning, the raw data will not be updated,
+ * so the time of the raw data is before scanning suspended. */
+ time_mono = ktime_get();
+ ret = cyapa_gen5_suspend_scanning(cyapa);
+ if (ret)
+ return ret;
+
+ /* 2. get the correct electrodes_rx number. */
+ if (cyapa->electrodes_rx == 0) {
+ /* Through the read global idac interface to get the Rx number.
+ * this value is useful to the raw data map.*/
+ data_size = 0;
+ err = cyapa_gen5_read_idac_data(cyapa,
+ GEN5_CMD_RETRIEVE_DATA_STRUCTURE,
+ GEN5_RETRIEVE_MUTUAL_PWC_DATA,
+ &data_size, &max, &min, &ave);
+ if (err || cyapa->electrodes_rx == 0)
+ goto resume_scanning;
+ }
+
+ /* 3. execuate panel scan. It must be executed before read data. */
+ err = cyapa_gen5_execute_panel_scan(cyapa);
+ if (err)
+ goto resume_scanning;
+
+ /* 4. retrive panel scan, mutual cap raw data. */
+ offset = GEN5_RAW_DATA_HEAD_SIZE;
+ err = cyapa_gen5_read_panel_scan_raw_data(cyapa,
+ GEN5_CMD_RETRIEVE_PANEL_SCAN,
+ GEN5_PANEL_SCAN_MUTUAL_DIFFCOUNT,
+ cyapa->electrodes_x * cyapa->electrodes_y,
+ &raw_cap_mutual_max, &raw_cap_mutual_min,
+ &raw_cap_mutual_ave,
+ cyapa->tp_raw_data + offset);
+ if (err)
+ goto resume_scanning;
+
+ offset += sizeof(s32) * cyapa->electrodes_x * cyapa->electrodes_y;
+
+ /* 5. retrive panel scan, self cap raw data. */
+ err = cyapa_gen5_read_panel_scan_raw_data(cyapa,
+ GEN5_CMD_RETRIEVE_PANEL_SCAN,
+ GEN5_PANEL_SCAN_SELF_DIFFCOUNT,
+ cyapa->electrodes_x + cyapa->electrodes_y,
+ &raw_cap_self_max, &raw_cap_self_min,
+ &raw_cap_self_ave,
+ cyapa->tp_raw_data + offset);
+ if (err)
+ goto resume_scanning;
+
+ offset += sizeof(s32) * (cyapa->electrodes_x + cyapa->electrodes_y);
+
+resume_scanning:
+ /* 6. resume Scanning*/
+ ret = cyapa_gen5_resume_scanning(cyapa);
+ if (ret || err)
+ return ret ? ret : err;
+
+ *((struct timeval *)&cyapa->tp_raw_data[0]) =
+ ktime_to_timeval(time_mono);
+ cyapa->tp_raw_data[16] = (u8)cyapa->electrodes_x;
+ cyapa->tp_raw_data[17] = (u8)cyapa->electrodes_y;
+ cyapa->tp_raw_data[18] = (u8)cyapa->x_origin;
+ cyapa->tp_raw_data[19] = (u8)cyapa->y_origin;
+ cyapa->tp_raw_data[20] = (u8)sizeof(s32);
+ cyapa->tp_raw_data[21] = (u8)sizeof(s32);
+ cyapa->tp_raw_data[22] = (u8)cyapa->electrodes_rx;
+ cyapa->tp_raw_data[23] = 0; /* reserved. */
+
+ cyapa->tp_raw_data_size = offset;
+ return 0;
+}
+
static bool cyapa_gen5_sort_system_info_data(struct cyapa *cyapa,
u8 *buf, int len)
{
@@ -2543,8 +2798,8 @@ const struct cyapa_dev_ops cyapa_gen5_ops = {
cyapa_gen5_show_baseline,
cyapa_gen5_do_calibrate,
- NULL,
- NULL,
+ cyapa_gen5_read_fw,
+ cyapa_gen5_read_raw_data,
cyapa_gen5_get_private_size,
cyapa_gen5_private_init,
This message and any attachments may contain Cypress (or its subsidiaries) confidential information. If it has been received in error, please advise the sender and immediately delete this message.
^ permalink raw reply related
* [PATCH v2 14/14] input: cyapa: add function to monitor LID close event to off trackpad device
From: Dudley Du @ 2014-06-30 6:45 UTC (permalink / raw)
To: Alan Stern, Dmitry Torokhov, patrikf@google.com,
Rafael J. Wysocki
Cc: Benson Leung, Daniel Kurtz, linux-input@vger.kernel.org,
linux-kernel@vger.kernel.org
Add the function to monitor lid close event to suspend and resume
trackpad device.
Because system suspend takes some time to trigger from user space,
and in that time, the lid panel of the laptop may couple with the
active trackpad. This may generate stray input events, which may
in turn cancel the suspend if the drivers use pm_wakup_event(), and
those input events may trigger something unwanted in the UI.
So this patch adds the function to do off the trackpad device quickly.
When the lid is closed, as soon as possible, the trakcpad device must
be off. And furthermore, the policy on lid close is not always to
enter suspend (lid closed with external display), and at this time,
the trackpad device must be disabled as well as again to avoid the
risk of generating stray events.
TEST=test on Chomebooks.
Signed-off-by: Du, Dudley <dudl@cypress.com>
---
diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
index 8d37032..760a43b 100644
--- a/drivers/input/mouse/cyapa.c
+++ b/drivers/input/mouse/cyapa.c
@@ -1166,6 +1166,140 @@ static const struct attribute_group cyapa_sysfs_group = {
.attrs = cyapa_sysfs_entries,
};
+
+/*
+ * We rely on EV_SW and SW_LID bits to identify a LID device, and hook
+ * up our filter to listen for SW_LID events to enable/disable touchpad when
+ * LID is open/closed.
+ */
+static const struct input_device_id lid_device_ids[] = {
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+ INPUT_DEVICE_ID_MATCH_SWBIT,
+ .evbit = { BIT_MASK(EV_SW) },
+ .swbit = { BIT_MASK(SW_LID) },
+ },
+ { },
+};
+
+static int lid_device_connect(struct input_handler *handler,
+ struct input_dev *dev,
+ const struct input_device_id *id)
+{
+ struct input_handle *lid_handle;
+ int error;
+
+ pr_info("cyapa: LID device: '%s' connected\n", dev->name);
+ lid_handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+ if (!lid_handle)
+ return -ENOMEM;
+
+ lid_handle->dev = dev;
+ lid_handle->handler = handler;
+ lid_handle->name = "lid_event_handler";
+ lid_handle->private = handler->private;
+
+ error = input_register_handle(lid_handle);
+ if (error) {
+ pr_err("Failed to register lid_event_handler, error %d\n",
+ error);
+ goto err_free;
+ }
+
+ error = input_open_device(lid_handle);
+ if (error) {
+ pr_err("Failed to open input device, error %d\n", error);
+ goto err_unregister;
+ }
+
+ return 0;
+err_unregister:
+ input_unregister_handle(lid_handle);
+err_free:
+ kfree(lid_handle);
+ return error;
+}
+
+static void lid_device_disconnect(struct input_handle *handle)
+{
+ input_close_device(handle);
+ input_unregister_handle(handle);
+ kfree(handle);
+}
+
+static bool lid_event_filter(struct input_handle *handle,
+ unsigned int type, unsigned int code, int value)
+{
+ struct cyapa *cyapa = handle->private;
+ struct device *dev = &cyapa->client->dev;
+
+ if (type == EV_SW && code == SW_LID) {
+ pr_info("cyapa %s: %s touch device\n",
+ dev_name(&cyapa->client->dev),
+ (value ? "disable" : "enable"));
+ if (cyapa->suspended) {
+ /*
+ * If the lid event filter is called while suspended,
+ * there is no guarantee that the underlying i2cs are
+ * resumed at this point, so it is not safe to issue
+ * the command to change power modes.
+ * Instead, rely on cyapa_resume to set us back to
+ * PWR_MODE_FULL_ACTIVE.
+ */
+ pr_info("cyapa %s: skipping lid pm change in suspend\n",
+ dev_name(&cyapa->client->dev));
+ return false;
+ }
+ if (value == 0) {
+ if (cyapa->ops->cyapa_set_power_mode)
+ cyapa->ops->cyapa_set_power_mode(cyapa,
+ PWR_MODE_FULL_ACTIVE, 0);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ } else {
+ pm_runtime_disable(dev);
+ if (cyapa->ops->cyapa_set_power_mode)
+ cyapa->ops->cyapa_set_power_mode(cyapa,
+ PWR_MODE_OFF, 0);
+ }
+ }
+
+ return false;
+}
+
+static void lid_event_register_handler(struct cyapa *cyapa)
+{
+ int error;
+ struct input_handler *lid_handler = &cyapa->lid_handler;
+
+ if (cyapa->lid_handler_registered) {
+ pr_err("lid handler is registered already\n");
+ return;
+ }
+
+ lid_handler->filter = lid_event_filter;
+ lid_handler->connect = lid_device_connect;
+ lid_handler->disconnect = lid_device_disconnect;
+ lid_handler->name = "cyapa_lid_event_handler";
+ lid_handler->id_table = lid_device_ids;
+ lid_handler->private = cyapa;
+
+ error = input_register_handler(lid_handler);
+ if (error) {
+ pr_err("Failed to register lid handler(%d)\n", error);
+ return;
+ }
+ cyapa->lid_handler_registered = true;
+}
+
+static void lid_event_unregister_handler(struct cyapa *cyapa)
+{
+ if (cyapa->lid_handler_registered) {
+ input_unregister_handler(&cyapa->lid_handler);
+ cyapa->lid_handler_registered = false;
+ }
+}
+
void cyapa_detect_async(void *data, async_cookie_t cookie)
{
struct cyapa *cyapa = (struct cyapa *)data;
@@ -1186,6 +1320,7 @@ static void cyapa_detect_and_start(void *data, async_cookie_t cookie)
cyapa_detect_async(data, cookie);
cyapa_start_runtime(cyapa);
+ lid_event_register_handler(cyapa);
}
static int cyapa_probe(struct i2c_client *client,
@@ -1324,6 +1459,7 @@ static int cyapa_remove(struct i2c_client *client)
mutex_destroy(&cyapa->debugfs_mutex);
input_unregister_device(cyapa->input);
+ lid_event_unregister_handler(cyapa);
if (cyapa->ops->cyapa_set_power_mode)
cyapa->ops->cyapa_set_power_mode(cyapa, PWR_MODE_OFF, 0);
i2c_set_clientdata(client, NULL);
@@ -1340,6 +1476,7 @@ static int cyapa_suspend(struct device *dev)
struct cyapa *cyapa = dev_get_drvdata(dev);
cyapa_disable_irq(cyapa);
+ cyapa->suspended = true;
/*
* Set trackpad device to idle mode if wakeup is allowed,
@@ -1382,6 +1519,7 @@ static int cyapa_resume(struct device *dev)
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
+ cyapa->suspended = false;
return 0;
}
#endif /* CONFIG_PM_SLEEP */
diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h
index 7f8c3d4..616db23 100644
--- a/drivers/input/mouse/cyapa.h
+++ b/drivers/input/mouse/cyapa.h
@@ -219,6 +219,7 @@ struct cyapa {
u8 runtime_suspend_power_mode;
u16 runtime_suspend_sleep_time;
#endif /* CONFIG_PM_RUNTIME */
+ bool suspended;
/* read from query data region. */
char product_id[16];
@@ -259,6 +260,9 @@ struct cyapa {
size_t tp_raw_data_size;
const struct cyapa_dev_ops *ops;
+
+ bool lid_handler_registered;
+ struct input_handler lid_handler;
};
This message and any attachments may contain Cypress (or its subsidiaries) confidential information. If it has been received in error, please advise the sender and immediately delete this message.
^ permalink raw reply related
* RE: [PATCH v2 0/14] input: cyapa: re-architecture driver to support multi-trackpads in one driver
From: Dudley Du @ 2014-06-30 6:54 UTC (permalink / raw)
To: Patrik Fimml
Cc: Dmitry Torokhov, Rafael J. Wysocki, Alan Stern, Benson Leung,
Lily Rui, Daniel Kurtz, linux-input@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <CAEn7tidaRxbLwQti8joDgq48K2YCAVE3uG-q6ZR=jEWAgm2tPg@mail.gmail.com>
Hi All,
Sorry for the disturb again.
The 14 caypa V2 patches I re-sent through 14:41 to 14:45 at 2014/6/30 still have some of them corrupted by the mail server.
Please ignore them. I will try to fix them.
Thanks,
Dudley
This message and any attachments may contain Cypress (or its subsidiaries) confidential information. If it has been received in error, please advise the sender and immediately delete this message.
^ permalink raw reply
* Re: [PATCH 1/1] drivers/hid/hid-picolcd_debugfs.c: remove unnecessary NULL test before debugfs_remove
From: Jiri Kosina @ 2014-06-30 7:54 UTC (permalink / raw)
To: Fabian Frederick; +Cc: linux-kernel, bonbons, linux-input
In-Reply-To: <1403962503-8507-1-git-send-email-fabf@skynet.be>
On Sat, 28 Jun 2014, Fabian Frederick wrote:
> Fix checkpatch warning:
> WARNING: debugfs_remove(NULL) is safe this check is probably not required
>
> Cc: Jiri Kosina <jkosina@suse.cz>
> Cc: linux-input@vger.kernel.org
> Signed-off-by: Fabian Frederick <fabf@skynet.be>
> ---
> drivers/hid/hid-picolcd_debugfs.c | 9 +++------
> 1 file changed, 3 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/hid/hid-picolcd_debugfs.c b/drivers/hid/hid-picolcd_debugfs.c
> index 024cdf3..3c13af6 100644
> --- a/drivers/hid/hid-picolcd_debugfs.c
> +++ b/drivers/hid/hid-picolcd_debugfs.c
> @@ -883,16 +883,13 @@ void picolcd_exit_devfs(struct picolcd_data *data)
>
> dent = data->debug_reset;
> data->debug_reset = NULL;
> - if (dent)
> - debugfs_remove(dent);
> + debugfs_remove(dent);
> dent = data->debug_eeprom;
> data->debug_eeprom = NULL;
> - if (dent)
> - debugfs_remove(dent);
> + debugfs_remove(dent);
> dent = data->debug_flash;
> data->debug_flash = NULL;
> - if (dent)
> - debugfs_remove(dent);
> + debugfs_remove(dent);
> mutex_destroy(&data->mutex_flash);
> }
Applied, thanks.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [PATCH] HID: roccat: Drop cast
From: Geert Uytterhoeven @ 2014-06-30 9:08 UTC (permalink / raw)
To: Joe Perches
Cc: Julia Lawall, Himangi Saraogi, Stefan Achatz, Jiri Kosina,
linux-input@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <1404066349.9064.60.camel@joe-AO725>
On Sun, Jun 29, 2014 at 8:25 PM, Joe Perches <joe@perches.com> wrote:
> I think I've seen code in the kernel like
> char *p2 = (void *)p;
> where p is const and p2 is dereferenced and set.
I can imagine there's code like that.
Still hoping for gcc to gain an option to warn about all casts, except in header
files...
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH 1/1] hid: sensor-hub, fix potential memory leak
From: Jiri Slaby @ 2014-06-30 9:34 UTC (permalink / raw)
To: jkosina
Cc: linux-kernel, linux-input, jirislaby, Jiri Slaby,
srinivas pandruvada
hsdev is not freed in sensor_hub_probe when kasprintf inside the for
loop fails. This is because hsdev is not set to platform_data yet (to
be freed by the code in the err_no_mem label). So free the memory
explicitly in the 'if' branch, as this is the only place where this is
(and will) be needed.
Reported-by: coverity
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: srinivas pandruvada <srinivas.pandruvada@intel.com>
Cc: Jiri Kosina <jkosina@suse.cz>
---
drivers/hid/hid-sensor-hub.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index a8d5c8faf8cf..584e17ce80e4 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -632,6 +632,7 @@ static int sensor_hub_probe(struct hid_device *hdev,
if (name == NULL) {
hid_err(hdev, "Failed MFD device name\n");
ret = -ENOMEM;
+ kfree(hsdev);
goto err_no_mem;
}
sd->hid_sensor_hub_client_devs[
--
2.0.0
^ permalink raw reply related
* Re: [PATCH v7 3/6] input: misc: Add driver for AXP20x Power Enable Key
From: Mark Rutland @ 2014-06-30 9:47 UTC (permalink / raw)
To: Carlo Caione
Cc: lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org,
boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org,
hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
linux-input-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
In-Reply-To: <1404066237-20234-4-git-send-email-carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org>
On Sun, Jun 29, 2014 at 07:23:54PM +0100, Carlo Caione wrote:
> This patch add support for the Power Enable Key found on MFD AXP202 and
> AXP209. Besides the basic support for the button, the driver adds two
> entries in sysfs to configure the time delay for power on/off.
>
> Signed-off-by: Carlo Caione <carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org>
> Acked-by: Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
> drivers/input/misc/Kconfig | 11 ++
> drivers/input/misc/Makefile | 1 +
> drivers/input/misc/axp20x-pek.c | 281 ++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 293 insertions(+)
> create mode 100644 drivers/input/misc/axp20x-pek.c
[...]
> +static int axp20x_pek_probe(struct platform_device *pdev)
> +{
> + struct axp20x_pek *axp20x_pek;
> + struct axp20x_dev *axp20x;
> + struct input_dev *idev;
> + int error;
> +
> + axp20x_pek = devm_kzalloc(&pdev->dev, sizeof(struct axp20x_pek),
> + GFP_KERNEL);
You can use sizeof(*axp20x_pek) here.
[...]
> +static struct platform_driver axp20x_pek_driver = {
> + .probe = axp20x_pek_probe,
> + .remove = axp20x_pek_remove,
> + .driver = {
> + .name = "axp20x-pek",
> + .owner = THIS_MODULE,
> + },
> +};
> +module_platform_driver(axp20x_pek_driver);
So this requires platform data rather than a DTB? Or have I missed
something?
Thanks,
Mark.
^ permalink raw reply
* Re: [PATCH v7 1/6] mfd: AXP20x: Add bindings documentation
From: Mark Rutland @ 2014-06-30 9:48 UTC (permalink / raw)
To: Carlo Caione
Cc: lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org,
boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org,
hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
linux-input-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
In-Reply-To: <1404066237-20234-2-git-send-email-carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org>
On Sun, Jun 29, 2014 at 07:23:52PM +0100, Carlo Caione wrote:
> Bindings documentation for the AXP20x driver. In this file also
> sub-nodes are documented.
>
> Signed-off-by: Carlo Caione <carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org>
> Acked-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
> Documentation/devicetree/bindings/mfd/axp20x.txt | 93 ++++++++++++++++++++++++
> 1 file changed, 93 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mfd/axp20x.txt
>
> diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
> new file mode 100644
> index 0000000..cc9e01b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
> @@ -0,0 +1,93 @@
> +AXP202/AXP209 device tree bindings
> +
> +The axp20x family current members :-
> +axp202 (X-Powers)
> +axp209 (X-Powers)
> +
> +Required properties:
> +- compatible: "x-powers,axp202" or "x-powers,axp209"
> +- reg: The I2C slave address for the AXP chip
> +- interrupt-parent: The parent interrupt controller
> +- interrupts: Interrupt specifiers for interrupt sources
How many, what are they?
> +- interrupt-controller: axp20x has its own internal IRQs
> +- #interrupt-cells: Should be set to 1
> +- acin-supply: The input supply for LDO1
> +- vin2-supply: The input supply for DCDC2
> +- vin3-supply: The input supply for DCDC3
> +- ldo24in-supply: The input supply for LDO2, LDO4
> +- ldo3in-supply: The input supply for LDO3
> +- ldo5in-supply: The input supply for LDO5
> +
> +- regulators: A node that houses a sub-node for each regulator. The regulators are
> + bound using their name as listed here: dcdc2, dcdc3, ldo1, ldo2,
> + ldo3, ldo4, ldo5. The bindings details of individual regulator
> + device can be found in:
> + Documentation/devicetree/bindings/regulator/regulator.txt with
> + the exception of x-powers,dcdc-freq
> +- x-powers,dcdc-freq: defines the work frequency of DC-DC in KHz
> + (range: 750-1875). Default: 1.5MHz
> +
> +Optional properties for DCDCs:
> +- x-powers,dcdc-workmode: 1 for PWM mode, 0 for AUTO mode
> + Default: AUTO mode
When would I want to select PWM mode, and why should this be in the DT?
Thanks,
Mark.
^ permalink raw reply
* Re: [PATCH 2/2 v3] HID: leds: move led_mode attribute to led-class devices in MSI GT683R driver
From: Johan Hovold @ 2014-06-30 10:39 UTC (permalink / raw)
To: Janne Kanniainen
Cc: johan, jkosina, greg, bjorn, cooloney, linux-kernel, linux-leds,
linux-usb, linux-input
In-Reply-To: <1403719989-19989-1-git-send-email-janne.kanniainen@gmail.com>
On Wed, Jun 25, 2014 at 09:13:09PM +0300, Janne Kanniainen wrote:
> Move led_mode attribute from HID device to led-class devices and rename it
> msi_mode. This will also fix race condition by using attribute-groups.
>
> Signed-off-by: Janne Kanniainen <janne.kanniainen@gmail.com>
> ---
>
> Changes in v3:
> - Style fixes
> - Rename sysfs-class-hid-driver-gt683r to sysfs-class-leds-driver-gt683r
>
> .../ABI/testing/sysfs-class-hid-driver-gt683r | 14 -----------
> .../ABI/testing/sysfs-class-leds-driver-gt683r | 16 +++++++++++++
> drivers/hid/hid-gt683r.c | 28 ++++++++++++----------
> 3 files changed, 32 insertions(+), 26 deletions(-)
> delete mode 100644 Documentation/ABI/testing/sysfs-class-hid-driver-gt683r
> create mode 100644 Documentation/ABI/testing/sysfs-class-leds-driver-gt683r
>
> diff --git a/Documentation/ABI/testing/sysfs-class-hid-driver-gt683r b/Documentation/ABI/testing/sysfs-class-hid-driver-gt683r
> deleted file mode 100644
> index 317e9d5..0000000
> --- a/Documentation/ABI/testing/sysfs-class-hid-driver-gt683r
> +++ /dev/null
> @@ -1,14 +0,0 @@
> -What: /sys/class/hidraw/<hidraw>/device/leds_mode
> -Date: Jun 2014
> -KernelVersion: 3.17
> -Contact: Janne Kanniainen <janne.kanniainen@gmail.com>
> -Description:
> - Set the mode of LEDs
> -
> - 0 - normal
> - 1 - audio
> - 2 - breathing
> -
> - Normal: LEDs are fully on when enabled
> - Audio: LEDs brightness depends on sound level
> - Breathing: LEDs brightness varies at human breathing rate
> \ No newline at end of file
> diff --git a/Documentation/ABI/testing/sysfs-class-leds-driver-gt683r b/Documentation/ABI/testing/sysfs-class-leds-driver-gt683r
> new file mode 100644
> index 0000000..29769fb
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-class-leds-driver-gt683r
> @@ -0,0 +1,16 @@
> +What: /sys/class/leds/<led>/msi_mode
The ABI-file name now sort of matches the attribute path and there are
examples of attributes being documented in this particular way, but
naming is far from consistent in Documentation/ABI.
Perhaps we should use the name field of the attribute group and kill two
birds with one stone by making the sysfs file name match the attribute
path, while also making it even more obvious that the mode attribute is a
driver specific attribute (and not a common led class one) by placing it
in a subdirectory.
That is, if you set the .name field to "gt683r" (and rename the
attribute and ABI-file again) then the file name and attribute path
could match:
Documentation/ABI/testing/sysfs-class-leds-gt683r
What: /sys/class/leds/<led>/gt683r/mode
Both patches look good otherwise.
Johan
^ permalink raw reply
* Re: [PATCH 2/2 v2] HID: leds: Use attribute-groups in MSI GT683R driver
From: Johan Hovold @ 2014-06-30 10:47 UTC (permalink / raw)
To: Bryan Wu
Cc: Jiri Kosina, Johan Hovold, Janne Kanniainen, Greg Kroah-Hartman,
Bjørn Mork, lkml, Linux LED Subsystem, linux-usb,
linux-input
In-Reply-To: <CAK5ve-JnqpogKaG1V=mfvKEHMPb8ma4Zeyz9rF4kT-W2Gj=p0A@mail.gmail.com>
On Wed, Jun 25, 2014 at 03:55:10PM -0700, Bryan Wu wrote:
> On Wed, Jun 25, 2014 at 12:09 PM, Jiri Kosina <jkosina@suse.cz> wrote:
> > On Wed, 25 Jun 2014, Johan Hovold wrote:
> >
> >> Did you see the attribute-race series I posted? Not sure how best to
> >> handle the dependency, as those patches should probably go in through
> >> the LEDs tree, while the first patch in that series (adding the groups
> >> field) is a dependency for this patch.
> >>
> >> Jiri, how would this best be solved?
> >
> > I think the best course of action here is to gather Acks from the
> > respective maintainers, and take the whole lot trough a single tree
> > (probably the leds tree in this case) to avoid unnecessary intra-tree
> > dependencies in a rather straighforward situation like this.
>
> I think the better place is HID/input tree, since this patch depends
> on the initial one which is not in my tree.
> I'm going to merge Johan's whole patchset and this patch probably
> depends Johan's work too.
Dmitry has ACKed the input-patch and Bryan has applied that one and the
leds-patches to his tree (of which the first one is a dependency of this
patch).
Jiri, are you saying that the gt683r-driver should go in through his
tree as well, that is all three patches including the first that you
have already applied? I just assumed your for-next branch was immutable,
but perhaps I was mistaken.
Thanks,
Johan
^ permalink raw reply
* Re: [PATCH 1/1] hid: sensor-hub, fix potential memory leak
From: Jiri Kosina @ 2014-06-30 11:22 UTC (permalink / raw)
To: Jiri Slaby; +Cc: linux-kernel, linux-input, jirislaby, srinivas pandruvada
In-Reply-To: <1404120888-10692-1-git-send-email-jslaby@suse.cz>
On Mon, 30 Jun 2014, Jiri Slaby wrote:
> hsdev is not freed in sensor_hub_probe when kasprintf inside the for
> loop fails. This is because hsdev is not set to platform_data yet (to
> be freed by the code in the err_no_mem label). So free the memory
> explicitly in the 'if' branch, as this is the only place where this is
> (and will) be needed.
>
> Reported-by: coverity
> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
> Cc: srinivas pandruvada <srinivas.pandruvada@intel.com>
> Cc: Jiri Kosina <jkosina@suse.cz>
> ---
> drivers/hid/hid-sensor-hub.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
> index a8d5c8faf8cf..584e17ce80e4 100644
> --- a/drivers/hid/hid-sensor-hub.c
> +++ b/drivers/hid/hid-sensor-hub.c
> @@ -632,6 +632,7 @@ static int sensor_hub_probe(struct hid_device *hdev,
> if (name == NULL) {
> hid_err(hdev, "Failed MFD device name\n");
> ret = -ENOMEM;
> + kfree(hsdev);
> goto err_no_mem;
> }
> sd->hid_sensor_hub_client_devs[
Applied, thanks.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [PATCH 2/2 v2] HID: leds: Use attribute-groups in MSI GT683R driver
From: Jiri Kosina @ 2014-06-30 11:33 UTC (permalink / raw)
To: Johan Hovold
Cc: Bryan Wu, Janne Kanniainen, Greg Kroah-Hartman, Bjørn Mork,
lkml, Linux LED Subsystem, linux-usb, linux-input
In-Reply-To: <20140630104744.GB2486@localhost>
On Mon, 30 Jun 2014, Johan Hovold wrote:
> > I think the better place is HID/input tree, since this patch depends
> > on the initial one which is not in my tree.
> > I'm going to merge Johan's whole patchset and this patch probably
> > depends Johan's work too.
>
> Dmitry has ACKed the input-patch and Bryan has applied that one and the
> leds-patches to his tree (of which the first one is a dependency of this
> patch).
>
> Jiri, are you saying that the gt683r-driver should go in through his
> tree as well, that is all three patches including the first that you
> have already applied? I just assumed your for-next branch was immutable,
> but perhaps I was mistaken.
Well, for-next branch is a collection of all the topic branches I am
queuing for the following merge window.
I am never really rebasing it, but I can definitely not include
'for-3.17/hid-gt683r' topic branch in the pile I will be sending to Linus
(all the scheduled branches are getting merged into 'for-linus' only when
merge window open). So the only potential conflict between hid.git and
Bryan's tree would be in linux-next (and probably there will be none, git
can handle duplicate patches nicely).
So once Bryan confirms he's queued it (please preserve my Signoff from my
tree), then I will just not include for-3.17/hid-gt683r branch in pull
request to Linus and all is fine.
Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [PATCH] Fixes kernel panic with Null pointer in hid-appleir.c
From: Jiri Kosina @ 2014-06-30 14:38 UTC (permalink / raw)
To: Nicholas Krause; +Cc: linux-input, linux-kernel
In-Reply-To: <1403281515-5508-1-git-send-email-xerofoify@gmail.com>
On Fri, 20 Jun 2014, Nicholas Krause wrote:
> In for loop of function appleir_input_configured we hit
> a Null pointer after the for loop due to array_size not
> being correct needs to be changed to input_dev->keycodemax.
>
> Signed-off-by: Nicholas Krause <xerofoify@gmail.com>
> ---
> drivers/hid/hid-appleir.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/hid/hid-appleir.c b/drivers/hid/hid-appleir.c
> index 0e6a42d..ab0a702 100644
> --- a/drivers/hid/hid-appleir.c
> +++ b/drivers/hid/hid-appleir.c
> @@ -272,7 +272,7 @@ static void appleir_input_configured(struct hid_device *hid,
> input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
>
> memcpy(appleir->keymap, appleir_key_table, sizeof(appleir->keymap));
> - for (i = 0; i < ARRAY_SIZE(appleir_key_table); i++)
> + for (i = 0; i < ARRAY_SIZE(input_dev->keycodemax); i++)
Ugh, how is this supposed to work? input_dev->keycodemax is int, not
array. I think you actually want sizeof(appleir->keymap) there.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [PATCH 0/4] Input: atmel_mxt_ts - make it work on Tegra
From: Stephen Warren @ 2014-06-30 16:11 UTC (permalink / raw)
To: Nick Dyer
Cc: Dmitry Torokhov, Benson Leung, Yufeng Shen, Daniel Kurtz,
linux-input@vger.kernel.org, Stephen Warren, Bowens, Alan
In-Reply-To: <537B8087.1040306@itdev.co.uk>
On 05/20/2014 10:19 AM, Nick Dyer wrote:
> Stephen Warren wrote:
>> On 05/16/2014 10:21 AM, Nick Dyer wrote:
>>> Thanks for this. Would you be happy for me to pick these changes up and
>>> include them along with the other work I am sending to Dmitry? I am just
>>> beginning to do various updates to the whole series, one of the things I
>>> need to sort out is the device tree support.
>>
>> That would be fine. I assume you'd only take the 2 Atmel driver patches.
>> I'll send the Tegra patches separately once the driver is merged.
>
> Great! Dmitry has merged some of the patches I sent now, so I'm just
> working on updating to take account of that and adding the device tree
> changes, and taking account of a couple of other review comments.
Nick, did you get anywhere with taking my DT patches and resending them?
Would you like me to resend them instead? I was really hoping to see
them working in 3.17. Unfortunately, I'm away for ~2.5 weeks starting in
a couple of days, so I won't be able to get them into 3.17 myself.
^ permalink raw reply
* Re: [PATCH v7 3/6] input: misc: Add driver for AXP20x Power Enable Key
From: Carlo Caione @ 2014-06-30 17:43 UTC (permalink / raw)
To: Mark Rutland
Cc: Carlo Caione, lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org,
boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org,
hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
linux-input-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
In-Reply-To: <20140630094712.GX7262@leverpostej>
On Mon, Jun 30, 2014 at 11:47 AM, Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org> wrote:
>> +static struct platform_driver axp20x_pek_driver = {
>> + .probe = axp20x_pek_probe,
>> + .remove = axp20x_pek_remove,
>> + .driver = {
>> + .name = "axp20x-pek",
>> + .owner = THIS_MODULE,
>> + },
>> +};
>> +module_platform_driver(axp20x_pek_driver);
>
> So this requires platform data rather than a DTB? Or have I missed
> something?
It is not loaded by DTB but by the MFD core driver (axp20x). So I
assume this is still a platform device.
Regards,
--
Carlo Caione
^ permalink raw reply
* [PATCH] Input: s3c2410_ts: Move to clk_prepare_enable/clk_disable_unprepare
From: Vasily Khoruzhick @ 2014-06-30 19:09 UTC (permalink / raw)
To: Ben Dooks, Kukjin Kim, Dmitry Torokhov, linux-arm-kernel,
linux-samsung-soc, linux-input
Cc: Vasily Khoruzhick
Use clk_prepare_enable/clk_disable_unprepare to make the driver
work properly with common clock framework.
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
---
drivers/input/touchscreen/s3c2410_ts.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
index 19cb247..c0e0baa 100644
--- a/drivers/input/touchscreen/s3c2410_ts.c
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -264,7 +264,7 @@ static int s3c2410ts_probe(struct platform_device *pdev)
return -ENOENT;
}
- clk_enable(ts.clock);
+ clk_prepare_enable(ts.clock);
dev_dbg(dev, "got and enabled clocks\n");
ts.irq_tc = ret = platform_get_irq(pdev, 0);
@@ -369,7 +369,7 @@ static int s3c2410ts_remove(struct platform_device *pdev)
free_irq(ts.irq_tc, ts.input);
del_timer_sync(&touch_timer);
- clk_disable(ts.clock);
+ clk_disable_unprepare(ts.clock);
clk_put(ts.clock);
input_unregister_device(ts.input);
@@ -383,7 +383,7 @@ static int s3c2410ts_suspend(struct device *dev)
{
writel(TSC_SLEEP, ts.io + S3C2410_ADCTSC);
disable_irq(ts.irq_tc);
- clk_disable(ts.clock);
+ clk_disable_unprepare(ts.clock);
return 0;
}
@@ -393,7 +393,7 @@ static int s3c2410ts_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct s3c2410_ts_mach_info *info = dev_get_platdata(&pdev->dev);
- clk_enable(ts.clock);
+ clk_prepare_enable(ts.clock);
enable_irq(ts.irq_tc);
/* Initialise registers */
--
2.0.0
^ permalink raw reply related
* Re: [PATCH v2 0/14] input: cyapa: re-architecture driver to support multi-trackpads in one driver
From: Patrik Fimml @ 2014-06-30 19:59 UTC (permalink / raw)
To: Dudley Du
Cc: Dmitry Torokhov, Rafael J. Wysocki, Alan Stern, Benson Leung,
Lily Rui, Daniel Kurtz, linux-input@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <77BC725C9062764F874D79F51E1F1A8F4C902B3B@S04-MBX01-01.s04.local>
Hi Dudley,
On Mon, Jun 30, 2014 at 05:43:06AM +0000, Dudley Du wrote:
> Attached are the patches files, I sent it firstly.
Thanks for the response, I was able to apply the patches now.
The attached files lack headers and commit messages though, so I don't have
fine-grained history in my git tree for convenient later review. The file names
suggest to me that you might just have copy-and-pasted the patches from
somewhere.
It would be great if you could attach them again in the format produced by "git
format-patch", with no further modifications done by hand. (If you feel the
need to do modifications, you should modify the actual commits e.g. with "git
rebase -i" before using format-patch.) Others can then simply import your
changes - including commit messages - into their tree with "git am".
Thanks,
Patrik
^ permalink raw reply
* [PATCH 01/15] Input - wacom: include and use linux/hid.h
From: Benjamin Tissoires @ 2014-06-30 21:26 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-input, linux-kernel, linuxwacom-devel
In-Reply-To: <1404163586-29582-1-git-send-email-benjamin.tissoires@redhat.com>
The current wacom code redefines constants that are already in linux/hid.h
This patch includes the official implementation and use it accross the code.
There is a conflict with HID_USAGE and others at the same level:
- in the wacom.ko implementation, those are the #define regarding the
value of the field in the report descriptor
- in the hid.h, those are bitmask
So add HDESC_ in their current definition.
Also, the struct hid_descriptor slightly differs from the linux/hid.h
point of view, so mark it as custom for this driver.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/tablet/wacom_sys.c | 53 +++++++++++++++++-----------------------
1 file changed, 22 insertions(+), 31 deletions(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 598efd4..e0c1cb2 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -13,28 +13,19 @@
#include "wacom_wac.h"
#include "wacom.h"
+#include <linux/hid.h>
/* defines to get HID report descriptor */
#define HID_DEVICET_HID (USB_TYPE_CLASS | 0x01)
#define HID_DEVICET_REPORT (USB_TYPE_CLASS | 0x02)
-#define HID_USAGE_UNDEFINED 0x00
-#define HID_USAGE_PAGE 0x05
-#define HID_USAGE_PAGE_DIGITIZER 0x0d
-#define HID_USAGE_PAGE_DESKTOP 0x01
-#define HID_USAGE 0x09
-#define HID_USAGE_X ((HID_USAGE_PAGE_DESKTOP << 16) | 0x30)
-#define HID_USAGE_Y ((HID_USAGE_PAGE_DESKTOP << 16) | 0x31)
-#define HID_USAGE_PRESSURE ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x30)
-#define HID_USAGE_X_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3d)
-#define HID_USAGE_Y_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3e)
-#define HID_USAGE_FINGER ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x22)
-#define HID_USAGE_STYLUS ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x20)
-#define HID_USAGE_CONTACTMAX ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x55)
-#define HID_COLLECTION 0xa1
-#define HID_COLLECTION_LOGICAL 0x02
-#define HID_COLLECTION_END 0xc0
-
-struct hid_descriptor {
+#define HID_HDESC_USAGE_UNDEFINED 0x00
+#define HID_HDESC_USAGE_PAGE 0x05
+#define HID_HDESC_USAGE 0x09
+#define HID_HDESC_COLLECTION 0xa1
+#define HID_HDESC_COLLECTION_LOGICAL 0x02
+#define HID_HDESC_COLLECTION_END 0xc0
+
+struct wac_hid_descriptor {
struct usb_descriptor_header header;
__le16 bcdHID;
u8 bCountryCode;
@@ -301,7 +292,7 @@ static void wacom_retrieve_report_data(struct usb_interface *intf,
* this after returning from this function.
*/
static int wacom_parse_hid(struct usb_interface *intf,
- struct hid_descriptor *hid_desc,
+ struct wac_hid_descriptor *hid_desc,
struct wacom_features *features)
{
struct usb_device *dev = interface_to_usbdev(intf);
@@ -334,14 +325,14 @@ static int wacom_parse_hid(struct usb_interface *intf,
for (i = 0; i < hid_desc->wDescriptorLength; i++) {
switch (report[i]) {
- case HID_USAGE_PAGE:
+ case HID_HDESC_USAGE_PAGE:
page = report[i + 1];
i++;
break;
- case HID_USAGE:
+ case HID_HDESC_USAGE:
switch (page << 16 | report[i + 1]) {
- case HID_USAGE_X:
+ case HID_GD_X:
if (finger) {
features->device_type = BTN_TOOL_FINGER;
/* touch device at least supports one touch point */
@@ -420,7 +411,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
}
break;
- case HID_USAGE_Y:
+ case HID_GD_Y:
if (finger) {
switch (features->type) {
case TABLETPC2FG:
@@ -472,7 +463,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
}
break;
- case HID_USAGE_FINGER:
+ case HID_DG_FINGER:
finger = 1;
i++;
break;
@@ -482,19 +473,19 @@ static int wacom_parse_hid(struct usb_interface *intf,
* X/Y values and some cases of invalid Digitizer X/Y
* values commonly reported.
*/
- case HID_USAGE_STYLUS:
+ case HID_DG_STYLUS:
pen = 1;
i++;
break;
- case HID_USAGE_CONTACTMAX:
+ case HID_DG_CONTACTMAX:
/* leave touch_max as is if predefined */
if (!features->touch_max)
wacom_retrieve_report_data(intf, features);
i++;
break;
- case HID_USAGE_PRESSURE:
+ case HID_DG_TIPPRESSURE:
if (pen) {
features->pressure_max =
get_unaligned_le16(&report[i + 3]);
@@ -504,15 +495,15 @@ static int wacom_parse_hid(struct usb_interface *intf,
}
break;
- case HID_COLLECTION_END:
+ case HID_HDESC_COLLECTION_END:
/* reset UsagePage and Finger */
finger = page = 0;
break;
- case HID_COLLECTION:
+ case HID_HDESC_COLLECTION:
i++;
switch (report[i]) {
- case HID_COLLECTION_LOGICAL:
+ case HID_HDESC_COLLECTION_LOGICAL:
i += wacom_parse_logical_collection(&report[i],
features);
break;
@@ -585,7 +576,7 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
{
int error = 0;
struct usb_host_interface *interface = intf->cur_altsetting;
- struct hid_descriptor *hid_desc;
+ struct wac_hid_descriptor *hid_desc;
/* default features */
features->device_type = BTN_TOOL_PEN;
--
2.0.0
^ permalink raw reply related
* [PATCH 02/15] Input - wacom: switch from an USB driver to a HID driver
From: Benjamin Tissoires @ 2014-06-30 21:26 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-input, linux-kernel, linuxwacom-devel
In-Reply-To: <1404163586-29582-1-git-send-email-benjamin.tissoires@redhat.com>
All USB Wacom tablets are actually HID devices.
For historical reasons, they are handled as plain USB devices.
The current code makes more and more reference to the HID subsystem
like implementing its own HID report descriptor parser to handle new
devices.
>From the user point of view, we can transparently switch from this state
to a driver handled in the HID subsystem and clean up a lot of USB specific
code in the wacom.ko driver.
The other benefit once the USB dependecies have been removed is that we can
use a tool like uhid to make regression tests and allow further cleanup or
new implementations without risking breaking current behaviors.
To match the current handling of devices in wacom_wac.c, we rely on the
hid_type set by usbhid. usbhid sets the hid_type to HID_TYPE_USBMOUSE when
it sees a USB boot mouse protocol declared and HID_TYPE_USBNONE when the
device is plain HID. There is thus a one to one matching between the list
of supported devices before and after the switch from USB to HID.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/hid/hid-core.c | 15 ++-
drivers/hid/hid-wacom.c | 2 +-
drivers/input/tablet/wacom.h | 6 +-
drivers/input/tablet/wacom_sys.c | 223 ++++++++++++++-------------------------
drivers/input/tablet/wacom_wac.c | 80 +++++++-------
drivers/input/tablet/wacom_wac.h | 4 +-
include/linux/hid.h | 1 +
7 files changed, 139 insertions(+), 192 deletions(-)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 2ce3f7a..9db1f42 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -782,10 +782,16 @@ static int hid_scan_report(struct hid_device *hid)
/*
* Vendor specific handlings
*/
- if ((hid->vendor == USB_VENDOR_ID_SYNAPTICS) &&
- (hid->group == HID_GROUP_GENERIC))
- /* hid-rmi should take care of them, not hid-generic */
- hid->group = HID_GROUP_RMI;
+ switch (hid->vendor) {
+ case USB_VENDOR_ID_SYNAPTICS:
+ if (hid->group == HID_GROUP_GENERIC)
+ /* hid-rmi should take care of them, not hid-generic */
+ hid->group = HID_GROUP_RMI;
+ break;
+ case USB_VENDOR_ID_WACOM:
+ hid->group = HID_GROUP_WACOM;
+ break;
+ }
vfree(parser);
return 0;
@@ -2340,7 +2346,6 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) },
- { HID_USB_DEVICE(USB_VENDOR_ID_WACOM, HID_ANY_ID) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT) },
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
index 902013e..4874f4e 100644
--- a/drivers/hid/hid-wacom.c
+++ b/drivers/hid/hid-wacom.c
@@ -960,7 +960,7 @@ static const struct hid_device_id wacom_devices[] = {
MODULE_DEVICE_TABLE(hid, wacom_devices);
static struct hid_driver wacom_driver = {
- .name = "wacom",
+ .name = "hid-wacom",
.id_table = wacom_devices,
.probe = wacom_probe,
.remove = wacom_remove,
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index 2386ad4..a931221 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -106,14 +106,12 @@ MODULE_LICENSE(DRIVER_LICENSE);
#define USB_VENDOR_ID_LENOVO 0x17ef
struct wacom {
- dma_addr_t data_dma;
struct usb_device *usbdev;
struct usb_interface *intf;
- struct urb *irq;
struct wacom_wac wacom_wac;
+ struct hid_device *hdev;
struct mutex lock;
struct work_struct work;
- bool open;
char phys[32];
struct wacom_led {
u8 select[2]; /* status led selector (0..3) */
@@ -131,7 +129,7 @@ static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
schedule_work(&wacom->work);
}
-extern const struct usb_device_id wacom_ids[];
+extern const struct hid_device_id wacom_ids[];
void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
void wacom_setup_device_quirks(struct wacom_features *features);
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index e0c1cb2..aa2a4d7 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -83,86 +83,40 @@ static int wacom_set_report(struct usb_interface *intf, u8 type, u8 id,
return retval;
}
-static void wacom_sys_irq(struct urb *urb)
+static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
+ u8 *raw_data, int size)
{
- struct wacom *wacom = urb->context;
- struct device *dev = &wacom->intf->dev;
- int retval;
+ struct wacom *wacom = hid_get_drvdata(hdev);
- switch (urb->status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dev_dbg(dev, "%s - urb shutting down with status: %d\n",
- __func__, urb->status);
- return;
- default:
- dev_dbg(dev, "%s - nonzero urb status received: %d\n",
- __func__, urb->status);
- goto exit;
- }
+ if (size > WACOM_PKGLEN_MAX)
+ return 1;
+
+ memcpy(wacom->wacom_wac.data, raw_data, size);
- wacom_wac_irq(&wacom->wacom_wac, urb->actual_length);
+ wacom_wac_irq(&wacom->wacom_wac, size);
- exit:
- usb_mark_last_busy(wacom->usbdev);
- retval = usb_submit_urb(urb, GFP_ATOMIC);
- if (retval)
- dev_err(dev, "%s - usb_submit_urb failed with result %d\n",
- __func__, retval);
+ return 0;
}
static int wacom_open(struct input_dev *dev)
{
struct wacom *wacom = input_get_drvdata(dev);
- int retval = 0;
-
- if (usb_autopm_get_interface(wacom->intf) < 0)
- return -EIO;
+ int retval;
mutex_lock(&wacom->lock);
-
- if (wacom->open)
- goto out;
-
- if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
- retval = -EIO;
- goto out;
- }
-
- wacom->open = true;
- wacom->intf->needs_remote_wakeup = 1;
-
-out:
+ retval = hid_hw_open(wacom->hdev);
mutex_unlock(&wacom->lock);
- usb_autopm_put_interface(wacom->intf);
+
return retval;
}
static void wacom_close(struct input_dev *dev)
{
struct wacom *wacom = input_get_drvdata(dev);
- int autopm_error;
-
- autopm_error = usb_autopm_get_interface(wacom->intf);
mutex_lock(&wacom->lock);
- if (!wacom->open)
- goto out;
-
- usb_kill_urb(wacom->irq);
- wacom->open = false;
- wacom->intf->needs_remote_wakeup = 0;
-
-out:
+ hid_hw_close(wacom->hdev);
mutex_unlock(&wacom->lock);
-
- if (!autopm_error)
- usb_autopm_put_interface(wacom->intf);
}
/*
@@ -807,7 +761,8 @@ out:
static ssize_t wacom_led_select_store(struct device *dev, int set_id,
const char *buf, size_t count)
{
- struct wacom *wacom = dev_get_drvdata(dev);
+ struct hid_device *hdev = dev_get_drvdata(dev);
+ struct wacom *wacom = hid_get_drvdata(hdev);
unsigned int id;
int err;
@@ -834,7 +789,8 @@ static ssize_t wacom_led##SET_ID##_select_store(struct device *dev, \
static ssize_t wacom_led##SET_ID##_select_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
- struct wacom *wacom = dev_get_drvdata(dev); \
+ struct hid_device *hdev = dev_get_drvdata(dev); \
+ struct wacom *wacom = hid_get_drvdata(hdev); \
return snprintf(buf, 2, "%d\n", wacom->led.select[SET_ID]); \
} \
static DEVICE_ATTR(status_led##SET_ID##_select, S_IWUSR | S_IRUSR, \
@@ -868,7 +824,8 @@ static ssize_t wacom_luminance_store(struct wacom *wacom, u8 *dest,
static ssize_t wacom_##name##_luminance_store(struct device *dev, \
struct device_attribute *attr, const char *buf, size_t count) \
{ \
- struct wacom *wacom = dev_get_drvdata(dev); \
+ struct hid_device *hdev = dev_get_drvdata(dev); \
+ struct wacom *wacom = hid_get_drvdata(hdev); \
\
return wacom_luminance_store(wacom, &wacom->led.field, \
buf, count); \
@@ -883,7 +840,8 @@ DEVICE_LUMINANCE_ATTR(buttons, img_lum);
static ssize_t wacom_button_image_store(struct device *dev, int button_id,
const char *buf, size_t count)
{
- struct wacom *wacom = dev_get_drvdata(dev);
+ struct hid_device *hdev = dev_get_drvdata(dev);
+ struct wacom *wacom = hid_get_drvdata(hdev);
int err;
if (count != 1024)
@@ -1197,6 +1155,7 @@ static void wacom_wireless_work(struct work_struct *work)
struct wacom *wacom = container_of(work, struct wacom, work);
struct usb_device *usbdev = wacom->usbdev;
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+ struct hid_device *hdev1, *hdev2;
struct wacom *wacom1, *wacom2;
struct wacom_wac *wacom_wac1, *wacom_wac2;
int error;
@@ -1209,14 +1168,16 @@ static void wacom_wireless_work(struct work_struct *work)
wacom_destroy_battery(wacom);
/* Stylus interface */
- wacom1 = usb_get_intfdata(usbdev->config->interface[1]);
+ hdev1 = usb_get_intfdata(usbdev->config->interface[1]);
+ wacom1 = hid_get_drvdata(hdev1);
wacom_wac1 = &(wacom1->wacom_wac);
if (wacom_wac1->input)
input_unregister_device(wacom_wac1->input);
wacom_wac1->input = NULL;
/* Touch interface */
- wacom2 = usb_get_intfdata(usbdev->config->interface[2]);
+ hdev2 = usb_get_intfdata(usbdev->config->interface[2]);
+ wacom2 = hid_get_drvdata(hdev2);
wacom_wac2 = &(wacom2->wacom_wac);
if (wacom_wac2->input)
input_unregister_device(wacom_wac2->input);
@@ -1225,20 +1186,20 @@ static void wacom_wireless_work(struct work_struct *work)
if (wacom_wac->pid == 0) {
dev_info(&wacom->intf->dev, "wireless tablet disconnected\n");
} else {
- const struct usb_device_id *id = wacom_ids;
+ const struct hid_device_id *id = wacom_ids;
dev_info(&wacom->intf->dev,
"wireless tablet connected with PID %x\n",
wacom_wac->pid);
- while (id->match_flags) {
- if (id->idVendor == USB_VENDOR_ID_WACOM &&
- id->idProduct == wacom_wac->pid)
+ while (id->bus) {
+ if (id->vendor == USB_VENDOR_ID_WACOM &&
+ id->product == wacom_wac->pid)
break;
id++;
}
- if (!id->match_flags) {
+ if (!id->bus) {
dev_info(&wacom->intf->dev,
"ignoring unknown PID.\n");
return;
@@ -1246,7 +1207,7 @@ static void wacom_wireless_work(struct work_struct *work)
/* Stylus interface */
wacom_wac1->features =
- *((struct wacom_features *)id->driver_info);
+ *((struct wacom_features *)id->driver_data);
wacom_wac1->features.device_type = BTN_TOOL_PEN;
snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen",
wacom_wac1->features.name);
@@ -1260,7 +1221,7 @@ static void wacom_wireless_work(struct work_struct *work)
if (wacom_wac1->features.touch_max ||
wacom_wac1->features.type == INTUOSHT) {
wacom_wac2->features =
- *((struct wacom_features *)id->driver_info);
+ *((struct wacom_features *)id->driver_data);
wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3;
wacom_wac2->features.device_type = BTN_TOOL_FINGER;
wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096;
@@ -1326,8 +1287,10 @@ static void wacom_calculate_res(struct wacom_features *features)
features->unitExpo);
}
-static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
+static int wacom_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
{
+ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor *endpoint;
struct wacom *wacom;
@@ -1335,34 +1298,29 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
struct wacom_features *features;
int error;
- if (!id->driver_info)
+ if (!id->driver_data)
return -EINVAL;
wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
if (!wacom)
return -ENOMEM;
+ hid_set_drvdata(hdev, wacom);
+ wacom->hdev = hdev;
+
wacom_wac = &wacom->wacom_wac;
- wacom_wac->features = *((struct wacom_features *)id->driver_info);
+ wacom_wac->features = *((struct wacom_features *)id->driver_data);
features = &wacom_wac->features;
if (features->pktlen > WACOM_PKGLEN_MAX) {
error = -EINVAL;
goto fail1;
}
- wacom_wac->data = usb_alloc_coherent(dev, WACOM_PKGLEN_MAX,
- GFP_KERNEL, &wacom->data_dma);
- if (!wacom_wac->data) {
- error = -ENOMEM;
+ if (features->check_for_hid_type && features->hid_type != hdev->type) {
+ error = -ENODEV;
goto fail1;
}
- wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
- if (!wacom->irq) {
- error = -ENOMEM;
- goto fail2;
- }
-
wacom->usbdev = dev;
wacom->intf = intf;
mutex_init(&wacom->lock);
@@ -1378,7 +1336,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
/* Retrieve the physical and logical size for touch devices */
error = wacom_retrieve_hid_descriptor(intf, features);
if (error)
- goto fail3;
+ goto fail1;
/*
* Intuos5 has no useful data about its touch interface in its
@@ -1426,38 +1384,38 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
other_dev = dev;
error = wacom_add_shared_data(wacom_wac, other_dev);
if (error)
- goto fail3;
+ goto fail1;
}
- usb_fill_int_urb(wacom->irq, dev,
- usb_rcvintpipe(dev, endpoint->bEndpointAddress),
- wacom_wac->data, features->pktlen,
- wacom_sys_irq, wacom, endpoint->bInterval);
- wacom->irq->transfer_dma = wacom->data_dma;
- wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
error = wacom_initialize_leds(wacom);
if (error)
- goto fail4;
+ goto fail2;
if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
error = wacom_register_input(wacom);
if (error)
- goto fail5;
+ goto fail3;
}
/* Note that if query fails it is not a hard failure */
wacom_query_tablet_data(intf, features);
- usb_set_intfdata(intf, wacom);
+ /* Regular HID work starts now */
+ error = hid_parse(hdev);
+ if (error) {
+ hid_err(hdev, "parse failed\n");
+ goto fail4;
+ }
- if (features->quirks & WACOM_QUIRK_MONITOR) {
- if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
- error = -EIO;
- goto fail5;
- }
+ error = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
+ if (error) {
+ hid_err(hdev, "hw start failed\n");
+ goto fail4;
}
+ if (features->quirks & WACOM_QUIRK_MONITOR)
+ error = hid_hw_open(hdev);
+
if (wacom_wac->features.type == INTUOSHT && wacom_wac->features.touch_max) {
if (wacom_wac->features.device_type == BTN_TOOL_FINGER)
wacom_wac->shared->touch_input = wacom_wac->input;
@@ -1465,21 +1423,21 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
return 0;
- fail5: wacom_destroy_leds(wacom);
- fail4: wacom_remove_shared_data(wacom_wac);
- fail3: usb_free_urb(wacom->irq);
- fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
+ fail4: if (wacom->wacom_wac.input)
+ input_unregister_device(wacom->wacom_wac.input);
+ fail3: wacom_destroy_leds(wacom);
+ fail2: wacom_remove_shared_data(wacom_wac);
fail1: kfree(wacom);
+ hid_set_drvdata(hdev, NULL);
return error;
}
-static void wacom_disconnect(struct usb_interface *intf)
+static void wacom_remove(struct hid_device *hdev)
{
- struct wacom *wacom = usb_get_intfdata(intf);
+ struct wacom *wacom = hid_get_drvdata(hdev);
- usb_set_intfdata(intf, NULL);
+ hid_hw_stop(hdev);
- usb_kill_urb(wacom->irq);
cancel_work_sync(&wacom->work);
if (wacom->wacom_wac.input)
input_unregister_device(wacom->wacom_wac.input);
@@ -1487,59 +1445,42 @@ static void wacom_disconnect(struct usb_interface *intf)
input_unregister_device(wacom->wacom_wac.pad_input);
wacom_destroy_battery(wacom);
wacom_destroy_leds(wacom);
- usb_free_urb(wacom->irq);
- usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
- wacom->wacom_wac.data, wacom->data_dma);
wacom_remove_shared_data(&wacom->wacom_wac);
- kfree(wacom);
-}
-
-static int wacom_suspend(struct usb_interface *intf, pm_message_t message)
-{
- struct wacom *wacom = usb_get_intfdata(intf);
-
- mutex_lock(&wacom->lock);
- usb_kill_urb(wacom->irq);
- mutex_unlock(&wacom->lock);
- return 0;
+ hid_set_drvdata(hdev, NULL);
+ kfree(wacom);
}
-static int wacom_resume(struct usb_interface *intf)
+static int wacom_resume(struct hid_device *hdev)
{
- struct wacom *wacom = usb_get_intfdata(intf);
+ struct wacom *wacom = hid_get_drvdata(hdev);
struct wacom_features *features = &wacom->wacom_wac.features;
- int rv = 0;
mutex_lock(&wacom->lock);
/* switch to wacom mode first */
- wacom_query_tablet_data(intf, features);
+ wacom_query_tablet_data(wacom->intf, features);
wacom_led_control(wacom);
- if ((wacom->open || (features->quirks & WACOM_QUIRK_MONITOR)) &&
- usb_submit_urb(wacom->irq, GFP_NOIO) < 0)
- rv = -EIO;
-
mutex_unlock(&wacom->lock);
- return rv;
+ return 0;
}
-static int wacom_reset_resume(struct usb_interface *intf)
+static int wacom_reset_resume(struct hid_device *hdev)
{
- return wacom_resume(intf);
+ return wacom_resume(hdev);
}
-static struct usb_driver wacom_driver = {
+static struct hid_driver wacom_driver = {
.name = "wacom",
.id_table = wacom_ids,
.probe = wacom_probe,
- .disconnect = wacom_disconnect,
- .suspend = wacom_suspend,
+ .remove = wacom_remove,
+#ifdef CONFIG_PM
.resume = wacom_resume,
.reset_resume = wacom_reset_resume,
- .supports_autosuspend = 1,
+#endif
+ .raw_event = wacom_raw_event,
};
-
-module_usb_driver(wacom_driver);
+module_hid_driver(wacom_driver);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index f170277..1c95ce7 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -2197,15 +2197,18 @@ static const struct wacom_features wacom_features_0x2A =
static const struct wacom_features wacom_features_0x314 =
{ "Wacom Intuos Pro S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047,
63, INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
- .touch_max = 16 };
+ .touch_max = 16,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x315 =
{ "Wacom Intuos Pro M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047,
63, INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
- .touch_max = 16 };
+ .touch_max = 16,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x317 =
{ "Wacom Intuos Pro L", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047,
63, INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
- .touch_max = 16 };
+ .touch_max = 16,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0xF4 =
{ "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104280, 65400, 2047,
63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
@@ -2215,7 +2218,8 @@ static const struct wacom_features wacom_features_0xF8 =
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 };
static const struct wacom_features wacom_features_0xF6 =
{ "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */
- .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10 };
+ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x3F =
{ "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023,
63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
@@ -2233,7 +2237,8 @@ static const struct wacom_features wacom_features_0xC7 =
0, PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xCE =
{ "Wacom DTU2231", WACOM_PKGLEN_GRAPHIRE, 47864, 27011, 511,
- 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBMOUSE };
static const struct wacom_features wacom_features_0xF0 =
{ "Wacom DTU1631", WACOM_PKGLEN_GRAPHIRE, 34623, 19553, 511,
0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2249,7 +2254,8 @@ static const struct wacom_features wacom_features_0x59 = /* Pen */
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D };
static const struct wacom_features wacom_features_0x5D = /* Touch */
{ "Wacom DTH2242", .type = WACOM_24HDT,
- .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10 };
+ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0xCC =
{ "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87000, 65400, 2047,
63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
@@ -2262,7 +2268,8 @@ static const struct wacom_features wacom_features_0x5B =
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e };
static const struct wacom_features wacom_features_0x5E =
{ "Wacom Cintiq 22HDT", .type = WACOM_24HDT,
- .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5b, .touch_max = 10 };
+ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5b, .touch_max = 10,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x90 =
{ "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255,
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2400,14 +2407,17 @@ static const struct wacom_features wacom_features_0x301 =
static const struct wacom_features wacom_features_0x302 =
{ "Wacom Intuos PT S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023,
31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 16 };
+ .touch_max = 16,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x303 =
{ "Wacom Intuos PT M", WACOM_PKGLEN_BBPEN, 21600, 13500, 1023,
31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 16 };
+ .touch_max = 16,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x30E =
{ "Wacom Intuos S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023,
- 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x6004 =
{ "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255,
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2417,22 +2427,18 @@ static const struct wacom_features wacom_features_0x0307 =
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 };
static const struct wacom_features wacom_features_0x0309 =
{ "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */
- .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10 };
-
-#define USB_DEVICE_WACOM(prod) \
- USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \
- .driver_info = (kernel_ulong_t)&wacom_features_##prod
+ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
-#define USB_DEVICE_DETAILED(prod, class, sub, proto) \
- USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_WACOM, prod, class, \
- sub, proto), \
- .driver_info = (kernel_ulong_t)&wacom_features_##prod
+#define USB_DEVICE_WACOM(prod) \
+ HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
+ .driver_data = (kernel_ulong_t)&wacom_features_##prod
#define USB_DEVICE_LENOVO(prod) \
- USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \
- .driver_info = (kernel_ulong_t)&wacom_features_##prod
+ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \
+ .driver_data = (kernel_ulong_t)&wacom_features_##prod
-const struct usb_device_id wacom_ids[] = {
+const struct hid_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x00) },
{ USB_DEVICE_WACOM(0x10) },
{ USB_DEVICE_WACOM(0x11) },
@@ -2478,9 +2484,9 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x45) },
{ USB_DEVICE_WACOM(0x57) },
{ USB_DEVICE_WACOM(0x59) },
- { USB_DEVICE_DETAILED(0x5D, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_WACOM(0x5D) },
{ USB_DEVICE_WACOM(0x5B) },
- { USB_DEVICE_DETAILED(0x5E, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_WACOM(0x5E) },
{ USB_DEVICE_WACOM(0xB0) },
{ USB_DEVICE_WACOM(0xB1) },
{ USB_DEVICE_WACOM(0xB2) },
@@ -2502,13 +2508,7 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0xC5) },
{ USB_DEVICE_WACOM(0xC6) },
{ USB_DEVICE_WACOM(0xC7) },
- /*
- * DTU-2231 has two interfaces on the same configuration,
- * only one is used.
- */
- { USB_DEVICE_DETAILED(0xCE, USB_CLASS_HID,
- USB_INTERFACE_SUBCLASS_BOOT,
- USB_INTERFACE_PROTOCOL_MOUSE) },
+ { USB_DEVICE_WACOM(0xCE) },
{ USB_DEVICE_WACOM(0x84) },
{ USB_DEVICE_WACOM(0xD0) },
{ USB_DEVICE_WACOM(0xD1) },
@@ -2546,13 +2546,13 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x116) },
{ USB_DEVICE_WACOM(0x300) },
{ USB_DEVICE_WACOM(0x301) },
- { USB_DEVICE_DETAILED(0x302, USB_CLASS_HID, 0, 0) },
- { USB_DEVICE_DETAILED(0x303, USB_CLASS_HID, 0, 0) },
- { USB_DEVICE_DETAILED(0x30E, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_WACOM(0x302) },
+ { USB_DEVICE_WACOM(0x303) },
+ { USB_DEVICE_WACOM(0x30E) },
{ USB_DEVICE_WACOM(0x304) },
- { USB_DEVICE_DETAILED(0x314, USB_CLASS_HID, 0, 0) },
- { USB_DEVICE_DETAILED(0x315, USB_CLASS_HID, 0, 0) },
- { USB_DEVICE_DETAILED(0x317, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_WACOM(0x314) },
+ { USB_DEVICE_WACOM(0x315) },
+ { USB_DEVICE_WACOM(0x317) },
{ USB_DEVICE_WACOM(0x4001) },
{ USB_DEVICE_WACOM(0x4004) },
{ USB_DEVICE_WACOM(0x5000) },
@@ -2560,12 +2560,12 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x47) },
{ USB_DEVICE_WACOM(0xF4) },
{ USB_DEVICE_WACOM(0xF8) },
- { USB_DEVICE_DETAILED(0xF6, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_WACOM(0xF6) },
{ USB_DEVICE_WACOM(0xFA) },
{ USB_DEVICE_WACOM(0xFB) },
{ USB_DEVICE_WACOM(0x0307) },
- { USB_DEVICE_DETAILED(0x0309, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_WACOM(0x0309) },
{ USB_DEVICE_LENOVO(0x6004) },
{ }
};
-MODULE_DEVICE_TABLE(usb, wacom_ids);
+MODULE_DEVICE_TABLE(hid, wacom_ids);
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index f48164c..8821a51 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -137,6 +137,8 @@ struct wacom_features {
unsigned touch_max;
int oVid;
int oPid;
+ bool check_for_hid_type;
+ int hid_type;
};
struct wacom_shared {
@@ -151,7 +153,7 @@ struct wacom_shared {
struct wacom_wac {
char name[WACOM_NAME_MAX];
char pad_name[WACOM_NAME_MAX];
- unsigned char *data;
+ unsigned char data[WACOM_PKGLEN_MAX];
int tool[2];
int id[2];
__u32 serial[2];
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 77632cf..9732299 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -309,6 +309,7 @@ struct hid_item {
* Vendor specific HID device groups
*/
#define HID_GROUP_RMI 0x0100
+#define HID_GROUP_WACOM 0x0101
/*
* This is the global environment of the parser. This information is
--
2.0.0
^ permalink raw reply related
* [PATCH 04/15] Input - wacom: use HID core to actually fetch the report descriptor
From: Benjamin Tissoires @ 2014-06-30 21:26 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-input, linux-kernel, linuxwacom-devel
In-Reply-To: <1404163586-29582-1-git-send-email-benjamin.tissoires@redhat.com>
HID core already retrieves the report descritor. There is no need
to ask ourself for one.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/tablet/wacom_sys.c | 70 ++++++----------------------------------
1 file changed, 10 insertions(+), 60 deletions(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index eb39314..cd3d936 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -15,9 +15,6 @@
#include "wacom.h"
#include <linux/hid.h>
-/* defines to get HID report descriptor */
-#define HID_DEVICET_HID (USB_TYPE_CLASS | 0x01)
-#define HID_DEVICET_REPORT (USB_TYPE_CLASS | 0x02)
#define HID_HDESC_USAGE_UNDEFINED 0x00
#define HID_HDESC_USAGE_PAGE 0x05
#define HID_HDESC_USAGE 0x09
@@ -25,15 +22,6 @@
#define HID_HDESC_COLLECTION_LOGICAL 0x02
#define HID_HDESC_COLLECTION_END 0xc0
-struct wac_hid_descriptor {
- struct usb_descriptor_header header;
- __le16 bcdHID;
- u8 bCountryCode;
- u8 bNumDescriptors;
- u8 bDescriptorType;
- __le16 wDescriptorLength;
-} __attribute__ ((packed));
-
#define WAC_MSG_RETRIES 5
#define WAC_CMD_LED_CONTROL 0x20
@@ -230,39 +218,14 @@ static void wacom_retrieve_report_data(struct hid_device *hdev,
* this after returning from this function.
*/
static int wacom_parse_hid(struct hid_device *hdev,
- struct wac_hid_descriptor *hid_desc,
struct wacom_features *features)
{
- struct wacom *wacom = hid_get_drvdata(hdev);
- struct usb_interface *intf = wacom->intf;
- struct usb_device *dev = interface_to_usbdev(intf);
- char limit = 0;
/* result has to be defined as int for some devices */
int result = 0, touch_max = 0;
int i = 0, page = 0, finger = 0, pen = 0;
- unsigned char *report;
+ unsigned char *report = hdev->rdesc;
- report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
- if (!report)
- return -ENOMEM;
-
- /* retrive report descriptors */
- do {
- result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_DESCRIPTOR,
- USB_RECIP_INTERFACE | USB_DIR_IN,
- HID_DEVICET_REPORT << 8,
- intf->altsetting[0].desc.bInterfaceNumber, /* interface */
- report,
- hid_desc->wDescriptorLength,
- 5000); /* 5 secs */
- } while (result < 0 && limit++ < WAC_MSG_RETRIES);
-
- /* No need to parse the Descriptor. It isn't an error though */
- if (result < 0)
- goto out;
-
- for (i = 0; i < hid_desc->wDescriptorLength; i++) {
+ for (i = 0; i < hdev->rsize; i++) {
switch (report[i]) {
case HID_HDESC_USAGE_PAGE:
@@ -452,11 +415,9 @@ static int wacom_parse_hid(struct hid_device *hdev,
}
}
- out:
if (!features->touch_max && touch_max)
features->touch_max = touch_max;
result = 0;
- kfree(report);
return result;
}
@@ -519,8 +480,6 @@ static int wacom_retrieve_hid_descriptor(struct hid_device *hdev,
int error = 0;
struct wacom *wacom = hid_get_drvdata(hdev);
struct usb_interface *intf = wacom->intf;
- struct usb_host_interface *interface = intf->cur_altsetting;
- struct wac_hid_descriptor *hid_desc;
/* default features */
features->device_type = BTN_TOOL_PEN;
@@ -549,17 +508,7 @@ static int wacom_retrieve_hid_descriptor(struct hid_device *hdev,
goto out;
}
- error = usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc);
- if (error) {
- error = usb_get_extra_descriptor(&interface->endpoint[0],
- HID_DEVICET_REPORT, &hid_desc);
- if (error) {
- hid_err(hdev,
- "can not retrieve extra class descriptor\n");
- goto out;
- }
- }
- error = wacom_parse_hid(hdev, hid_desc, features);
+ error = wacom_parse_hid(hdev, features);
out:
return error;
@@ -1299,6 +1248,13 @@ static int wacom_probe(struct hid_device *hdev,
hid_set_drvdata(hdev, wacom);
wacom->hdev = hdev;
+ /* ask for the report descriptor to be loaded by HID */
+ error = hid_parse(hdev);
+ if (error) {
+ hid_err(hdev, "parse failed\n");
+ goto fail1;
+ }
+
wacom_wac = &wacom->wacom_wac;
wacom_wac->features = *((struct wacom_features *)id->driver_data);
features = &wacom_wac->features;
@@ -1392,12 +1348,6 @@ static int wacom_probe(struct hid_device *hdev,
wacom_query_tablet_data(hdev, features);
/* Regular HID work starts now */
- error = hid_parse(hdev);
- if (error) {
- hid_err(hdev, "parse failed\n");
- goto fail4;
- }
-
error = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
if (error) {
hid_err(hdev, "hw start failed\n");
--
2.0.0
^ permalink raw reply related
* [PATCH 05/15] Input - wacom: compute the HID report size to get the actual packet size
From: Benjamin Tissoires @ 2014-06-30 21:26 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-input, linux-kernel, linuxwacom-devel
In-Reply-To: <1404163586-29582-1-git-send-email-benjamin.tissoires@redhat.com>
This removes an USB dependency and is more accurate: the computed pktlen
is the actual maximum size of the reports forwarded by the device.
Given that the pktlen is correctly computed/validated, we can store it now
in the features struct instead of having a special handling in the rest of
the code.
Likewise, this information is not mandatory anymore in the description
of devices in wacom_wac.c. They will be removed in a separate patch.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/tablet/wacom_sys.c | 58 ++++++++++++++++++----------------------
1 file changed, 26 insertions(+), 32 deletions(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index cd3d936..3f1cee6 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -149,7 +149,6 @@ static int wacom_parse_logical_collection(unsigned char *report,
if (features->type == BAMBOO_PT) {
/* Logical collection is only used by 3rd gen Bamboo Touch */
- features->pktlen = WACOM_PKGLEN_BBTOUCH3;
features->device_type = BTN_TOOL_FINGER;
features->x_max = features->y_max =
@@ -240,29 +239,6 @@ static int wacom_parse_hid(struct hid_device *hdev,
features->device_type = BTN_TOOL_FINGER;
/* touch device at least supports one touch point */
touch_max = 1;
- switch (features->type) {
- case TABLETPC2FG:
- features->pktlen = WACOM_PKGLEN_TPC2FG;
- break;
-
- case MTSCREEN:
- case WACOM_24HDT:
- features->pktlen = WACOM_PKGLEN_MTOUCH;
- break;
-
- case MTTPC:
- case MTTPC_B:
- features->pktlen = WACOM_PKGLEN_MTTPC;
- break;
-
- case BAMBOO_PT:
- features->pktlen = WACOM_PKGLEN_BBTOUCH;
- break;
-
- default:
- features->pktlen = WACOM_PKGLEN_GRAPHIRE;
- break;
- }
switch (features->type) {
case BAMBOO_PT:
@@ -305,8 +281,6 @@ static int wacom_parse_hid(struct hid_device *hdev,
}
} else if (pen) {
/* penabled only accepts exact bytes of data */
- if (features->type >= TABLETPC)
- features->pktlen = WACOM_PKGLEN_GRAPHIRE;
features->device_type = BTN_TOOL_PEN;
features->x_max =
get_unaligned_le16(&report[i + 3]);
@@ -1227,12 +1201,34 @@ static void wacom_calculate_res(struct wacom_features *features)
features->unitExpo);
}
+static int wacom_hid_report_len(struct hid_report *report)
+{
+ /* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */
+ return ((report->size - 1) >> 3) + 1 + (report->id > 0);
+}
+
+static size_t wacom_compute_pktlen(struct hid_device *hdev)
+{
+ struct hid_report_enum *report_enum;
+ struct hid_report *report;
+ size_t size = 0;
+
+ report_enum = hdev->report_enum + HID_INPUT_REPORT;
+
+ list_for_each_entry(report, &report_enum->report_list, list) {
+ size_t report_size = wacom_hid_report_len(report);
+ if (report_size > size)
+ size = report_size;
+ }
+
+ return size;
+}
+
static int wacom_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
struct usb_device *dev = interface_to_usbdev(intf);
- struct usb_endpoint_descriptor *endpoint;
struct wacom *wacom;
struct wacom_wac *wacom_wac;
struct wacom_features *features;
@@ -1258,6 +1254,7 @@ static int wacom_probe(struct hid_device *hdev,
wacom_wac = &wacom->wacom_wac;
wacom_wac->features = *((struct wacom_features *)id->driver_data);
features = &wacom_wac->features;
+ features->pktlen = wacom_compute_pktlen(hdev);
if (features->pktlen > WACOM_PKGLEN_MAX) {
error = -EINVAL;
goto fail1;
@@ -1275,8 +1272,6 @@ static int wacom_probe(struct hid_device *hdev,
usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
- endpoint = &intf->cur_altsetting->endpoint[0].desc;
-
/* set the default size in case we do not get them from hid */
wacom_set_default_phy(features);
@@ -1287,13 +1282,12 @@ static int wacom_probe(struct hid_device *hdev,
/*
* Intuos5 has no useful data about its touch interface in its
- * HID descriptor. If this is the touch interface (wMaxPacketSize
+ * HID descriptor. If this is the touch interface (PacketSize
* of WACOM_PKGLEN_BBTOUCH3), override the table values.
*/
if (features->type >= INTUOS5S && features->type <= INTUOSHT) {
- if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) {
+ if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
features->device_type = BTN_TOOL_FINGER;
- features->pktlen = WACOM_PKGLEN_BBTOUCH3;
features->x_max = 4096;
features->y_max = 4096;
--
2.0.0
^ permalink raw reply related
* [PATCH 06/15] Input - wacom: install LED/OLED sysfs files in the HID device instead of USB
From: Benjamin Tissoires @ 2014-06-30 21:26 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-input, linux-kernel, linuxwacom-devel
In-Reply-To: <1404163586-29582-1-git-send-email-benjamin.tissoires@redhat.com>
Removes one more dependency over USB, but requires some changes in
the user space to find the sysfs files correctly.
This patch breaks the user space. However, the number of program
accessing the LEDs is quite limited and we can easily patch them
to handle the new HID behavior.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/tablet/wacom_sys.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 3f1cee6..6f4bf6d 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -675,7 +675,7 @@ out:
static ssize_t wacom_led_select_store(struct device *dev, int set_id,
const char *buf, size_t count)
{
- struct hid_device *hdev = dev_get_drvdata(dev);
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
struct wacom *wacom = hid_get_drvdata(hdev);
unsigned int id;
int err;
@@ -703,7 +703,7 @@ static ssize_t wacom_led##SET_ID##_select_store(struct device *dev, \
static ssize_t wacom_led##SET_ID##_select_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
- struct hid_device *hdev = dev_get_drvdata(dev); \
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);\
struct wacom *wacom = hid_get_drvdata(hdev); \
return snprintf(buf, 2, "%d\n", wacom->led.select[SET_ID]); \
} \
@@ -738,7 +738,7 @@ static ssize_t wacom_luminance_store(struct wacom *wacom, u8 *dest,
static ssize_t wacom_##name##_luminance_store(struct device *dev, \
struct device_attribute *attr, const char *buf, size_t count) \
{ \
- struct hid_device *hdev = dev_get_drvdata(dev); \
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);\
struct wacom *wacom = hid_get_drvdata(hdev); \
\
return wacom_luminance_store(wacom, &wacom->led.field, \
@@ -754,7 +754,7 @@ DEVICE_LUMINANCE_ATTR(buttons, img_lum);
static ssize_t wacom_button_image_store(struct device *dev, int button_id,
const char *buf, size_t count)
{
- struct hid_device *hdev = dev_get_drvdata(dev);
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
struct wacom *wacom = hid_get_drvdata(hdev);
int err;
@@ -845,7 +845,7 @@ static int wacom_initialize_leds(struct wacom *wacom)
wacom->led.llv = 10;
wacom->led.hlv = 20;
wacom->led.img_lum = 10;
- error = sysfs_create_group(&wacom->intf->dev.kobj,
+ error = sysfs_create_group(&wacom->hdev->dev.kobj,
&intuos4_led_attr_group);
break;
@@ -857,7 +857,7 @@ static int wacom_initialize_leds(struct wacom *wacom)
wacom->led.hlv = 0;
wacom->led.img_lum = 0;
- error = sysfs_create_group(&wacom->intf->dev.kobj,
+ error = sysfs_create_group(&wacom->hdev->dev.kobj,
&cintiq_led_attr_group);
break;
@@ -874,7 +874,7 @@ static int wacom_initialize_leds(struct wacom *wacom)
wacom->led.hlv = 0;
wacom->led.img_lum = 0;
- error = sysfs_create_group(&wacom->intf->dev.kobj,
+ error = sysfs_create_group(&wacom->hdev->dev.kobj,
&intuos5_led_attr_group);
} else
return 0;
@@ -885,7 +885,7 @@ static int wacom_initialize_leds(struct wacom *wacom)
}
if (error) {
- dev_err(&wacom->intf->dev,
+ hid_err(wacom->hdev,
"cannot create sysfs group err: %d\n", error);
return error;
}
@@ -906,13 +906,13 @@ static void wacom_destroy_leds(struct wacom *wacom)
case INTUOS4S:
case INTUOS4:
case INTUOS4L:
- sysfs_remove_group(&wacom->intf->dev.kobj,
+ sysfs_remove_group(&wacom->hdev->dev.kobj,
&intuos4_led_attr_group);
break;
case WACOM_24HD:
case WACOM_21UX2:
- sysfs_remove_group(&wacom->intf->dev.kobj,
+ sysfs_remove_group(&wacom->hdev->dev.kobj,
&cintiq_led_attr_group);
break;
@@ -923,7 +923,7 @@ static void wacom_destroy_leds(struct wacom *wacom)
case INTUOSPM:
case INTUOSPL:
if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN)
- sysfs_remove_group(&wacom->intf->dev.kobj,
+ sysfs_remove_group(&wacom->hdev->dev.kobj,
&intuos5_led_attr_group);
break;
}
--
2.0.0
^ permalink raw reply related
* [PATCH 08/15] Input - wacom: remove usb dependency for siblings devices
From: Benjamin Tissoires @ 2014-06-30 21:26 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-input, linux-kernel, linuxwacom-devel
In-Reply-To: <1404163586-29582-1-git-send-email-benjamin.tissoires@redhat.com>
Wacom tablets can share different physical sensors on one physical device.
These are called siblings in the code. The current way of implementation
relies on the USB topology to be able to share data amongs those sensors.
We can replace the code to match a HID subsystem, without involving the USB
topology:
- the first probed sensor does not find any siblings in the list
wacom_udev_list, so it creates its own wacom_hdev_data with its own
struct hid_device
- the other sensor checks the current list of siblings in wacom_hdev_data,
and if there is a match, it associates itself to the matched device.
To be sure that we are not associating different sensors from different
physical devices, we also check for the phys path of the hid device which
contains the USB topology.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/tablet/wacom_sys.c | 75 +++++++++++++++++++---------------------
1 file changed, 35 insertions(+), 40 deletions(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 0d0397d..6fe7a6c 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -488,46 +488,45 @@ static int wacom_retrieve_hid_descriptor(struct hid_device *hdev,
return error;
}
-struct wacom_usbdev_data {
+struct wacom_hdev_data {
struct list_head list;
struct kref kref;
- struct usb_device *dev;
+ struct hid_device *dev;
struct wacom_shared shared;
};
static LIST_HEAD(wacom_udev_list);
static DEFINE_MUTEX(wacom_udev_list_lock);
-static struct usb_device *wacom_get_sibling(struct usb_device *dev, int vendor, int product)
+static bool wacom_are_sibling(struct hid_device *hdev,
+ struct hid_device *sibling)
{
- int port1;
- struct usb_device *sibling;
-
- if (vendor == 0 && product == 0)
- return dev;
-
- if (dev->parent == NULL)
- return NULL;
-
- usb_hub_for_each_child(dev->parent, port1, sibling) {
- struct usb_device_descriptor *d;
- if (sibling == NULL)
- continue;
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct wacom_features *features = &wacom->wacom_wac.features;
+ int vid = features->oVid;
+ int pid = features->oPid;
- d = &sibling->descriptor;
- if (d->idVendor == vendor && d->idProduct == product)
- return sibling;
+ if (vid == 0 && pid == 0) {
+ vid = hdev->vendor;
+ pid = hdev->product;
}
- return NULL;
+ if (vid != sibling->vendor || pid != sibling->product)
+ return false;
+
+ /*
+ * Compare the physical path.
+ * Dump the last two chars which should contain the input number.
+ */
+ return !strncmp(hdev->phys, sibling->phys, strlen(hdev->phys) - 2);
}
-static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev)
+static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev)
{
- struct wacom_usbdev_data *data;
+ struct wacom_hdev_data *data;
list_for_each_entry(data, &wacom_udev_list, list) {
- if (data->dev == dev) {
+ if (wacom_are_sibling(hdev, data->dev)) {
kref_get(&data->kref);
return data;
}
@@ -536,28 +535,29 @@ static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev)
return NULL;
}
-static int wacom_add_shared_data(struct wacom_wac *wacom,
- struct usb_device *dev)
+static int wacom_add_shared_data(struct hid_device *hdev)
{
- struct wacom_usbdev_data *data;
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+ struct wacom_hdev_data *data;
int retval = 0;
mutex_lock(&wacom_udev_list_lock);
- data = wacom_get_usbdev_data(dev);
+ data = wacom_get_hdev_data(hdev);
if (!data) {
- data = kzalloc(sizeof(struct wacom_usbdev_data), GFP_KERNEL);
+ data = kzalloc(sizeof(struct wacom_hdev_data), GFP_KERNEL);
if (!data) {
retval = -ENOMEM;
goto out;
}
kref_init(&data->kref);
- data->dev = dev;
+ data->dev = hdev;
list_add_tail(&data->list, &wacom_udev_list);
}
- wacom->shared = &data->shared;
+ wacom_wac->shared = &data->shared;
out:
mutex_unlock(&wacom_udev_list_lock);
@@ -566,8 +566,8 @@ out:
static void wacom_release_shared_data(struct kref *kref)
{
- struct wacom_usbdev_data *data =
- container_of(kref, struct wacom_usbdev_data, kref);
+ struct wacom_hdev_data *data =
+ container_of(kref, struct wacom_hdev_data, kref);
mutex_lock(&wacom_udev_list_lock);
list_del(&data->list);
@@ -578,10 +578,10 @@ static void wacom_release_shared_data(struct kref *kref)
static void wacom_remove_shared_data(struct wacom_wac *wacom)
{
- struct wacom_usbdev_data *data;
+ struct wacom_hdev_data *data;
if (wacom->shared) {
- data = container_of(wacom->shared, struct wacom_usbdev_data, shared);
+ data = container_of(wacom->shared, struct wacom_hdev_data, shared);
kref_put(&data->kref, wacom_release_shared_data);
wacom->shared = NULL;
}
@@ -1311,8 +1311,6 @@ static int wacom_probe(struct hid_device *hdev,
"%s Pad", features->name);
if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
- struct usb_device *other_dev;
-
/* Append the device type to the name */
if (features->device_type != BTN_TOOL_FINGER)
strlcat(wacom_wac->name, " Pen", WACOM_NAME_MAX);
@@ -1321,10 +1319,7 @@ static int wacom_probe(struct hid_device *hdev,
else
strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX);
- other_dev = wacom_get_sibling(dev, features->oVid, features->oPid);
- if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL)
- other_dev = dev;
- error = wacom_add_shared_data(wacom_wac, other_dev);
+ error = wacom_add_shared_data(hdev);
if (error)
goto fail1;
}
--
2.0.0
^ permalink raw reply related
* [PATCH 09/15] Input - wacom: register power device at the HID level
From: Benjamin Tissoires @ 2014-06-30 21:26 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-input, linux-kernel, linuxwacom-devel
In-Reply-To: <1404163586-29582-1-git-send-email-benjamin.tissoires@redhat.com>
Use the HID device as the parent for the power device when dealing with
a wireless receiver.
Removes one more usb dependency and does not break user space.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/tablet/wacom_sys.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 6fe7a6c..2313f1a 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -969,12 +969,12 @@ static int wacom_initialize_battery(struct wacom *wacom)
wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY;
wacom->battery.use_for_apm = 0;
- error = power_supply_register(&wacom->usbdev->dev,
+ error = power_supply_register(&wacom->hdev->dev,
&wacom->battery);
if (!error)
power_supply_powers(&wacom->battery,
- &wacom->usbdev->dev);
+ &wacom->hdev->dev);
}
return error;
--
2.0.0
^ permalink raw reply related
* [PATCH 10/15] Input - wacom: use hid_info instead of plain dev_info
From: Benjamin Tissoires @ 2014-06-30 21:26 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-input, linux-kernel, linuxwacom-devel
In-Reply-To: <1404163586-29582-1-git-send-email-benjamin.tissoires@redhat.com>
Removes one more need of usb and intf.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/tablet/wacom_sys.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 2313f1a..2208b4a 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -1101,12 +1101,11 @@ static void wacom_wireless_work(struct work_struct *work)
wacom_wac2->input = NULL;
if (wacom_wac->pid == 0) {
- dev_info(&wacom->intf->dev, "wireless tablet disconnected\n");
+ hid_info(wacom->hdev, "wireless tablet disconnected\n");
} else {
const struct hid_device_id *id = wacom_ids;
- dev_info(&wacom->intf->dev,
- "wireless tablet connected with PID %x\n",
+ hid_info(wacom->hdev, "wireless tablet connected with PID %x\n",
wacom_wac->pid);
while (id->bus) {
@@ -1117,8 +1116,7 @@ static void wacom_wireless_work(struct work_struct *work)
}
if (!id->bus) {
- dev_info(&wacom->intf->dev,
- "ignoring unknown PID.\n");
+ hid_info(wacom->hdev, "ignoring unknown PID.\n");
return;
}
--
2.0.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox