If we want to have one input device per remote, it's better to have our own struct wacom_remote which is dynamically allocated.
Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com> Acked-by: Ping Cheng <pi...@wacom.com> Signed-off-by: Jiri Kosina <jkos...@suse.cz> [aaron.sko...@wacom.com: Imported into input-wacom repository (83e6b40)] Signed-off-by: Aaron Armstrong Skomra <aaron.sko...@wacom.com> [aaron.sko...@wacom.com: Backported from input-wacom repository (3c055ea)] Signed-off-by: Aaron Armstrong Skomra <aaron.sko...@wacom.com> --- 2.6.38/wacom.h | 13 +++-- 2.6.38/wacom_sys.c | 144 ++++++++++++++++++++++++++++++----------------------- 2.6.38/wacom_wac.c | 12 +++-- 2.6.38/wacom_wac.h | 2 +- 3.17/wacom.h | 13 +++-- 3.17/wacom_sys.c | 133 ++++++++++++++++++++++++++++--------------------- 3.17/wacom_wac.c | 12 +++-- 3.17/wacom_wac.h | 2 +- 3.7/wacom.h | 13 +++-- 3.7/wacom_sys.c | 142 +++++++++++++++++++++++++++++----------------------- 3.7/wacom_wac.c | 12 +++-- 3.7/wacom_wac.h | 2 +- 12 files changed, 288 insertions(+), 212 deletions(-) diff --git a/2.6.38/wacom.h b/2.6.38/wacom.h index b4470b3..e0c7be1 100644 --- a/2.6.38/wacom.h +++ b/2.6.38/wacom.h @@ -119,6 +119,14 @@ enum wacom_worker { WACOM_WORKER_REMOTE, }; +struct wacom_remote { + spinlock_t remote_lock; + struct kfifo remote_fifo; + struct kobject *remote_dir; + struct attribute_group remote_group[WACOM_MAX_REMOTES]; + __u32 serial[WACOM_MAX_REMOTES]; +}; + struct wacom { dma_addr_t data_dma; struct usb_device *usbdev; @@ -129,8 +137,7 @@ struct wacom { struct work_struct wireless_work; struct work_struct battery_work; struct work_struct remote_work; - spinlock_t remote_lock; - struct kfifo remote_fifo; + struct wacom_remote *remote; bool open; char phys[32]; struct wacom_led { @@ -140,8 +147,6 @@ struct wacom { u8 img_lum; /* OLED matrix display brightness */ } led; struct power_supply battery; - struct kobject *remote_dir; - struct attribute_group remote_group[5]; }; static inline void wacom_schedule_work(struct wacom_wac *wacom_wac, diff --git a/2.6.38/wacom_sys.c b/2.6.38/wacom_sys.c index 12a3c66..303814b 100644 --- a/2.6.38/wacom_sys.c +++ b/2.6.38/wacom_sys.c @@ -1275,19 +1275,17 @@ DEVICE_EKR_ATTR_GROUP(4); static int wacom_remote_create_attr_group(struct wacom *wacom, __u32 serial, int index) { int error = 0; - char *buf; - struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_remote *remote = wacom->remote; - wacom_wac->serial[index] = serial; + remote->serial[index] = serial; - buf = kzalloc(WAC_REMOTE_SERIAL_MAX_STRLEN, GFP_KERNEL); - if (!buf) + remote->remote_group[index].name = kasprintf(GFP_KERNEL, "%d", serial); + if (!remote->remote_group[index].name) return -ENOMEM; - snprintf(buf, WAC_REMOTE_SERIAL_MAX_STRLEN, "%d", serial); - wacom->remote_group[index].name = buf; - error = sysfs_create_group(wacom->remote_dir, - &wacom->remote_group[index]); + error = sysfs_create_group(remote->remote_dir, + &remote->remote_group[index]); + if (error) { dev_err(&wacom->intf->dev, "cannot create sysfs group err: %d\n", error); @@ -1299,21 +1297,21 @@ static int wacom_remote_create_attr_group(struct wacom *wacom, __u32 serial, int static void wacom_remote_destroy_attr_group(struct wacom *wacom, __u32 serial) { - struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_remote *remote = wacom->remote; int i; if (!serial) return; for (i = 0; i < WACOM_MAX_REMOTES; i++) { - if (wacom_wac->serial[i] == serial) { - wacom_wac->serial[i] = 0; + if (remote->serial[i] == serial) { + remote->serial[i] = 0; wacom->led.select[i] = WACOM_STATUS_UNKNOWN; - if (wacom->remote_group[i].name) { - sysfs_remove_group(wacom->remote_dir, - &wacom->remote_group[i]); - kfree(wacom->remote_group[i].name); - wacom->remote_group[i].name = NULL; + if (remote->remote_group[i].name) { + sysfs_remove_group(remote->remote_dir, + &remote->remote_group[i]); + kfree((char *)remote->remote_group[i].name); + remote->remote_group[i].name = NULL; } } } @@ -1375,27 +1373,65 @@ static const struct attribute *remote_unpair_attrs[] = { NULL }; -static int wacom_initialize_remote(struct wacom *wacom) +static void wacom_remotes_destroy(void *data) +{ + struct wacom *wacom = data; + struct wacom_remote *remote = wacom->remote; + int i; + + if (!remote) + return; + + for (i = 0; i < WACOM_MAX_REMOTES; i++) { + if (wacom->remote->remote_group[i].name) { + wacom_remote_destroy_attr_group(wacom, + wacom->wacom_wac.serial[i]); + } + } + kobject_put(remote->remote_dir); + kfifo_free(&remote->remote_fifo); + wacom->remote = NULL; +} + +static int wacom_initialize_remotes(struct wacom *wacom) { int error = 0; - struct wacom_wac *wacom_wac = &(wacom->wacom_wac); + struct wacom_remote *remote; int i; if (wacom->wacom_wac.features.type != REMOTE) return 0; - wacom->remote_group[0] = remote0_serial_group; - wacom->remote_group[1] = remote1_serial_group; - wacom->remote_group[2] = remote2_serial_group; - wacom->remote_group[3] = remote3_serial_group; - wacom->remote_group[4] = remote4_serial_group; + remote = devm_kzalloc(&wacom->usbdev->dev, sizeof(*wacom->remote), + GFP_KERNEL); + if (!remote) + return -ENOMEM; + + wacom->remote = remote; + + spin_lock_init(&remote->remote_lock); - wacom->remote_dir = kobject_create_and_add("wacom_remote", - &wacom->intf->dev.kobj); - if (!wacom->remote_dir) + error = kfifo_alloc(&remote->remote_fifo, + 5 * sizeof(struct wacom_remote_data), + GFP_KERNEL); + if (error) { + dev_err(&wacom->intf->dev, "failed allocating remote_fifo\n"); return -ENOMEM; + } - error = sysfs_create_files(wacom->remote_dir, remote_unpair_attrs); + remote->remote_group[0] = remote0_serial_group; + remote->remote_group[1] = remote1_serial_group; + remote->remote_group[2] = remote2_serial_group; + remote->remote_group[3] = remote3_serial_group; + remote->remote_group[4] = remote4_serial_group; + + remote->remote_dir = kobject_create_and_add("wacom_remote", + &wacom->intf->dev.kobj); + + if (!remote->remote_dir) + return -ENOMEM; + + error = sysfs_create_files(remote->remote_dir, remote_unpair_attrs); if (error) { dev_err(&wacom->intf->dev, @@ -1405,7 +1441,7 @@ static int wacom_initialize_remote(struct wacom *wacom) for (i = 0; i < WACOM_MAX_REMOTES; i++) { wacom->led.select[i] = WACOM_STATUS_UNKNOWN; - wacom_wac->serial[i] = 0; + remote->serial[i] = 0; } return 0; @@ -1617,58 +1653,58 @@ static void wacom_remote_work(struct work_struct *work) { struct wacom *wacom = container_of(work, struct wacom, remote_work); struct device *dev = &wacom->intf->dev; - struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_remote *remote = wacom->remote; struct wacom_remote_data data; unsigned long flags; unsigned int count; u32 serial; int i, k; - spin_lock_irqsave(&wacom->remote_lock, flags); + spin_lock_irqsave(&remote->remote_lock, flags); - count = kfifo_out(&wacom->remote_fifo, &data, sizeof(data)); + count = kfifo_out(&remote->remote_fifo, &data, sizeof(data)); if (count != sizeof(data)) { dev_err(dev, "workitem triggered without status available\n"); - spin_unlock_irqrestore(&wacom->remote_lock, flags); + spin_unlock_irqrestore(&remote->remote_lock, flags); return; } - if (!kfifo_is_empty(&wacom->remote_fifo)) + if (!kfifo_is_empty(&remote->remote_fifo)) wacom_schedule_work(&wacom->wacom_wac, WACOM_WORKER_REMOTE); - spin_unlock_irqrestore(&wacom->remote_lock, flags); + spin_unlock_irqrestore(&remote->remote_lock, flags); for (i = 0; i < WACOM_MAX_REMOTES; i++) { serial = data.remote[i].serial; if (data.remote[i].connected) { - if (wacom_wac->serial[i] == serial) + if (remote->serial[i] == serial) continue; - if (wacom_wac->serial[i]) { + if (remote->serial[i]) { wacom_remote_destroy_attr_group(wacom, - wacom_wac->serial[i]); + remote->serial[i]); } /* A remote can pair more than once with an EKR, * check to make sure this serial isn't already paired. */ for (k = 0; k < WACOM_MAX_REMOTES; k++) { - if (wacom_wac->serial[k] == serial) + if (remote->serial[k] == serial) break; } if (k < WACOM_MAX_REMOTES) { - wacom_wac->serial[i] = serial; + remote->serial[i] = serial; continue; } wacom_remote_create_attr_group(wacom, serial, i); - } else if (wacom_wac->serial[i]) { + } else if (remote->serial[i]) { wacom_remote_destroy_attr_group(wacom, - wacom_wac->serial[i]); + remote->serial[i]); } } } @@ -1721,16 +1757,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i INIT_WORK(&wacom->wireless_work, wacom_wireless_work); INIT_WORK(&wacom->battery_work, wacom_battery_work); INIT_WORK(&wacom->remote_work, wacom_remote_work); - spin_lock_init(&wacom->remote_lock); - - if (kfifo_alloc(&wacom->remote_fifo, - 5 * sizeof(struct wacom_remote_data), - GFP_KERNEL)) { - dev_err(&wacom->intf->dev, - "%s:failed allocating remote_fifo\n", __func__); - error = -ENOMEM; - goto fail2; - } usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); @@ -1795,7 +1821,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i goto fail4; if (wacom->wacom_wac.features.type == REMOTE) { - error = wacom_initialize_remote(wacom); + error = wacom_initialize_remotes(wacom); if (error) goto fail4; } @@ -1814,7 +1840,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i fail4: wacom_remove_shared_data(wacom_wac); fail3: usb_free_urb(wacom->irq); wacom_destroy_battery(wacom); - kfifo_free(&wacom->remote_fifo); fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); fail1: return error; @@ -1823,7 +1848,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i static void wacom_disconnect(struct usb_interface *intf) { struct wacom *wacom = usb_get_intfdata(intf); - int i; usb_set_intfdata(intf, NULL); @@ -1831,14 +1855,8 @@ static void wacom_disconnect(struct usb_interface *intf) cancel_work_sync(&wacom->wireless_work); cancel_work_sync(&wacom->battery_work); cancel_work_sync(&wacom->remote_work); - kfifo_free(&wacom->remote_fifo); - for (i = 0; i < WACOM_MAX_REMOTES; i++) { - if (wacom->remote_group[i].name) { - wacom_remote_destroy_attr_group(wacom, - wacom->wacom_wac.serial[i]); - } - } - kobject_put(wacom->remote_dir); + + wacom_remotes_destroy(wacom); wacom_unregister_inputs(wacom); wacom_destroy_battery(wacom); usb_free_urb(wacom->irq); diff --git a/2.6.38/wacom_wac.c b/2.6.38/wacom_wac.c index 4361d55..7ccd5bc 100644 --- a/2.6.38/wacom_wac.c +++ b/2.6.38/wacom_wac.c @@ -703,6 +703,7 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) struct input_dev *input = wacom_wac->input; struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); struct wacom_features *features = &wacom_wac->features; + struct wacom_remote *remote = wacom->remote; int bat_charging, bat_percent, touch_ring_mode; __u32 serial; int i; @@ -755,7 +756,7 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) touch_ring_mode = (data[11] & 0xC0) >> 6; for (i = 0; i < WACOM_MAX_REMOTES; i++) { - if (wacom_wac->serial[i] == serial) + if (remote->serial[i] == serial) wacom->led.select[i] = touch_ring_mode; } @@ -775,6 +776,7 @@ static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); struct device *dev = &wacom->intf->dev; unsigned char *data = wacom_wac->data; + struct wacom_remote *remote = wacom->remote; struct wacom_remote_data remote_data; unsigned long flags; int i, ret; @@ -793,16 +795,16 @@ static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) remote_data.remote[i].connected = connected; } - spin_lock_irqsave(&wacom->remote_lock, flags); + spin_lock_irqsave(&remote->remote_lock, flags); - ret = kfifo_in(&wacom->remote_fifo, &remote_data, sizeof(remote_data)); + ret = kfifo_in(&remote->remote_fifo, &remote_data, sizeof(remote_data)); if (ret != sizeof(remote_data)) { - spin_unlock_irqrestore(&wacom->remote_lock, flags); + spin_unlock_irqrestore(&remote->remote_lock, flags); dev_err(dev, "Can't queue Remote status event.\n"); return; } - spin_unlock_irqrestore(&wacom->remote_lock, flags); + spin_unlock_irqrestore(&remote->remote_lock, flags); wacom_schedule_work(wacom_wac, WACOM_WORKER_REMOTE); } diff --git a/2.6.38/wacom_wac.h b/2.6.38/wacom_wac.h index 17ca409..abe52fb 100644 --- a/2.6.38/wacom_wac.h +++ b/2.6.38/wacom_wac.h @@ -178,7 +178,7 @@ struct wacom_wac { unsigned char *data; int tool[2]; int id[2]; - __u32 serial[5]; + __u32 serial[2]; bool reporting_data; struct wacom_features features; struct wacom_shared *shared; diff --git a/3.17/wacom.h b/3.17/wacom.h index 6b7032f..d2c9548 100644 --- a/3.17/wacom.h +++ b/3.17/wacom.h @@ -130,6 +130,14 @@ struct wacom_group_leds { u8 select; /* status led selector (0..3) */ }; +struct wacom_remote { + spinlock_t remote_lock; + struct kfifo remote_fifo; + struct kobject *remote_dir; + struct attribute_group remote_group[WACOM_MAX_REMOTES]; + __u32 serial[WACOM_MAX_REMOTES]; +}; + struct wacom { struct usb_device *usbdev; struct usb_interface *intf; @@ -139,8 +147,7 @@ struct wacom { struct work_struct wireless_work; struct work_struct battery_work; struct work_struct remote_work; - spinlock_t remote_lock; - struct kfifo remote_fifo; + struct wacom_remote *remote; struct wacom_leds { struct wacom_group_leds *groups; u8 llv; /* status led brightness no button (1..127) */ @@ -156,8 +163,6 @@ struct wacom { struct power_supply battery; struct power_supply ac; #endif - struct kobject *remote_dir; - struct attribute_group remote_group[5]; bool resources; }; diff --git a/3.17/wacom_sys.c b/3.17/wacom_sys.c index 696efa5..6acf07f 100644 --- a/3.17/wacom_sys.c +++ b/3.17/wacom_sys.c @@ -1350,18 +1350,18 @@ static int wacom_remote_create_attr_group(struct wacom *wacom, __u32 serial, int index) { int error = 0; - struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_remote *remote = wacom->remote; - wacom_wac->serial[index] = serial; + remote->serial[index] = serial; - wacom->remote_group[index].name = devm_kasprintf(&wacom->hdev->dev, - GFP_KERNEL, - "%d", serial); - if (!wacom->remote_group[index].name) + remote->remote_group[index].name = devm_kasprintf(&wacom->hdev->dev, + GFP_KERNEL, + "%d", serial); + if (!remote->remote_group[index].name) return -ENOMEM; - error = sysfs_create_group(wacom->remote_dir, - &wacom->remote_group[index]); + error = sysfs_create_group(remote->remote_dir, + &remote->remote_group[index]); if (error) { hid_err(wacom->hdev, "cannot create sysfs group err: %d\n", error); @@ -1373,22 +1373,22 @@ static int wacom_remote_create_attr_group(struct wacom *wacom, __u32 serial, static void wacom_remote_destroy_attr_group(struct wacom *wacom, __u32 serial) { - struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_remote *remote = wacom->remote; int i; if (!serial) return; for (i = 0; i < WACOM_MAX_REMOTES; i++) { - if (wacom_wac->serial[i] == serial) { - wacom_wac->serial[i] = 0; + if (remote->serial[i] == serial) { + remote->serial[i] = 0; wacom->led.groups[i].select = WACOM_STATUS_UNKNOWN; - if (wacom->remote_group[i].name) { - sysfs_remove_group(wacom->remote_dir, - &wacom->remote_group[i]); + if (remote->remote_group[i].name) { + sysfs_remove_group(remote->remote_dir, + &remote->remote_group[i]); devm_kfree(&wacom->hdev->dev, - (char *)wacom->remote_group[i].name); - wacom->remote_group[i].name = NULL; + (char *)remote->remote_group[i].name); + remote->remote_group[i].name = NULL; } } } @@ -1450,27 +1450,57 @@ static const struct attribute *remote_unpair_attrs[] = { NULL }; -static int wacom_initialize_remote(struct wacom *wacom) +static void wacom_remotes_destroy(void *data) +{ + struct wacom *wacom = data; + struct wacom_remote *remote = wacom->remote; + + if (!remote) + return; + + kobject_put(remote->remote_dir); + kfifo_free(&remote->remote_fifo); + wacom->remote = NULL; +} + +static int wacom_initialize_remotes(struct wacom *wacom) { int error = 0; - struct wacom_wac *wacom_wac = &(wacom->wacom_wac); + struct wacom_remote *remote; int i; if (wacom->wacom_wac.features.type != REMOTE) return 0; - wacom->remote_group[0] = remote0_serial_group; - wacom->remote_group[1] = remote1_serial_group; - wacom->remote_group[2] = remote2_serial_group; - wacom->remote_group[3] = remote3_serial_group; - wacom->remote_group[4] = remote4_serial_group; + remote = devm_kzalloc(&wacom->hdev->dev, sizeof(*wacom->remote), + GFP_KERNEL); + if (!remote) + return -ENOMEM; - wacom->remote_dir = kobject_create_and_add("wacom_remote", - &wacom->hdev->dev.kobj); - if (!wacom->remote_dir) + wacom->remote = remote; + + spin_lock_init(&remote->remote_lock); + + error = kfifo_alloc(&remote->remote_fifo, + 5 * sizeof(struct wacom_remote_data), + GFP_KERNEL); + if (error) { + hid_err(wacom->hdev, "failed allocating remote_fifo\n"); return -ENOMEM; + } - error = sysfs_create_files(wacom->remote_dir, remote_unpair_attrs); + remote->remote_group[0] = remote0_serial_group; + remote->remote_group[1] = remote1_serial_group; + remote->remote_group[2] = remote2_serial_group; + remote->remote_group[3] = remote3_serial_group; + remote->remote_group[4] = remote4_serial_group; + + remote->remote_dir = kobject_create_and_add("wacom_remote", + &wacom->hdev->dev.kobj); + if (!remote->remote_dir) + return -ENOMEM; + + error = sysfs_create_files(remote->remote_dir, remote_unpair_attrs); if (error) { hid_err(wacom->hdev, @@ -1480,9 +1510,14 @@ static int wacom_initialize_remote(struct wacom *wacom) for (i = 0; i < WACOM_MAX_REMOTES; i++) { wacom->led.groups[i].select = WACOM_STATUS_UNKNOWN; - wacom_wac->serial[i] = 0; + remote->serial[i] = 0; } + error = devm_add_action_or_reset(&wacom->hdev->dev, + wacom_remotes_destroy, wacom); + if (error) + return error; + return 0; } @@ -1796,7 +1831,7 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless) if (error) goto fail_leds; - error = wacom_initialize_remote(wacom); + error = wacom_initialize_remotes(wacom); if (error) goto fail_remote; } @@ -1852,7 +1887,6 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless) fail_quirks: hid_hw_stop(hdev); fail_hw_start: - kobject_put(wacom->remote_dir); fail_remote: fail_leds: fail_register_inputs: @@ -1956,58 +1990,58 @@ fail: static void wacom_remote_work(struct work_struct *work) { struct wacom *wacom = container_of(work, struct wacom, remote_work); - struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_remote *remote = wacom->remote; struct wacom_remote_data data; unsigned long flags; unsigned int count; u32 serial; int i, k; - spin_lock_irqsave(&wacom->remote_lock, flags); + spin_lock_irqsave(&remote->remote_lock, flags); - count = kfifo_out(&wacom->remote_fifo, &data, sizeof(data)); + count = kfifo_out(&remote->remote_fifo, &data, sizeof(data)); if (count != sizeof(data)) { hid_err(wacom->hdev, "workitem triggered without status available\n"); - spin_unlock_irqrestore(&wacom->remote_lock, flags); + spin_unlock_irqrestore(&remote->remote_lock, flags); return; } - if (!kfifo_is_empty(&wacom->remote_fifo)) + if (!kfifo_is_empty(&remote->remote_fifo)) wacom_schedule_work(&wacom->wacom_wac, WACOM_WORKER_REMOTE); - spin_unlock_irqrestore(&wacom->remote_lock, flags); + spin_unlock_irqrestore(&remote->remote_lock, flags); for (i = 0; i < WACOM_MAX_REMOTES; i++) { serial = data.remote[i].serial; if (data.remote[i].connected) { - if (wacom_wac->serial[i] == serial) + if (remote->serial[i] == serial) continue; - if (wacom_wac->serial[i]) { + if (remote->serial[i]) { wacom_remote_destroy_attr_group(wacom, - wacom_wac->serial[i]); + remote->serial[i]); } /* A remote can pair more than once with an EKR, * check to make sure this serial isn't already paired. */ for (k = 0; k < WACOM_MAX_REMOTES; k++) { - if (wacom_wac->serial[k] == serial) + if (remote->serial[k] == serial) break; } if (k < WACOM_MAX_REMOTES) { - wacom_wac->serial[i] = serial; + remote->serial[i] = serial; continue; } wacom_remote_create_attr_group(wacom, serial, i); - } else if (wacom_wac->serial[i]) { + } else if (remote->serial[i]) { wacom_remote_destroy_attr_group(wacom, - wacom_wac->serial[i]); + remote->serial[i]); } } } @@ -2055,16 +2089,6 @@ static int wacom_probe(struct hid_device *hdev, INIT_WORK(&wacom->wireless_work, wacom_wireless_work); INIT_WORK(&wacom->battery_work, wacom_battery_work); INIT_WORK(&wacom->remote_work, wacom_remote_work); - spin_lock_init(&wacom->remote_lock); - - if (kfifo_alloc(&wacom->remote_fifo, - 5 * sizeof(struct wacom_remote_data), - GFP_KERNEL)) { - dev_err(&hdev->dev, - "%s:failed allocating remote_fifo\n", __func__); - error = -ENOMEM; - goto fail_type; - } /* ask for the report descriptor to be loaded by HID */ error = hid_parse(hdev); @@ -2088,7 +2112,6 @@ static int wacom_probe(struct hid_device *hdev, return 0; fail_parse: - kfifo_free(&wacom->remote_fifo); fail_type: hid_set_drvdata(hdev, NULL); return error; @@ -2108,8 +2131,6 @@ static void wacom_remove(struct hid_device *hdev) cancel_work_sync(&wacom->wireless_work); cancel_work_sync(&wacom->battery_work); cancel_work_sync(&wacom->remote_work); - kfifo_free(&wacom->remote_fifo); - kobject_put(wacom->remote_dir); if (hdev->bus == BUS_BLUETOOTH) device_remove_file(&hdev->dev, &dev_attr_speed); #if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0) diff --git a/3.17/wacom_wac.c b/3.17/wacom_wac.c index 298d5b3..7ab1553 100644 --- a/3.17/wacom_wac.c +++ b/3.17/wacom_wac.c @@ -759,6 +759,7 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) unsigned char *data = wacom_wac->data; struct input_dev *input = wacom_wac->pad_input; struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); + struct wacom_remote *remote = wacom->remote; struct wacom_features *features = &wacom_wac->features; int bat_charging, bat_percent, touch_ring_mode; __u32 serial; @@ -813,7 +814,7 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) touch_ring_mode = (data[11] & 0xC0) >> 6; for (i = 0; i < WACOM_MAX_REMOTES; i++) { - if (wacom_wac->serial[i] == serial) + if (remote->serial[i] == serial) wacom->led.groups[i].select = touch_ring_mode; } @@ -833,6 +834,7 @@ static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) { struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); unsigned char *data = wacom_wac->data; + struct wacom_remote *remote = wacom->remote; struct wacom_remote_data remote_data; unsigned long flags; int i, ret; @@ -851,16 +853,16 @@ static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) remote_data.remote[i].connected = connected; } - spin_lock_irqsave(&wacom->remote_lock, flags); + spin_lock_irqsave(&remote->remote_lock, flags); - ret = kfifo_in(&wacom->remote_fifo, &remote_data, sizeof(remote_data)); + ret = kfifo_in(&remote->remote_fifo, &remote_data, sizeof(remote_data)); if (ret != sizeof(remote_data)) { - spin_unlock_irqrestore(&wacom->remote_lock, flags); + spin_unlock_irqrestore(&remote->remote_lock, flags); hid_err(wacom->hdev, "Can't queue Remote status event.\n"); return; } - spin_unlock_irqrestore(&wacom->remote_lock, flags); + spin_unlock_irqrestore(&remote->remote_lock, flags); wacom_schedule_work(wacom_wac, WACOM_WORKER_REMOTE); } diff --git a/3.17/wacom_wac.h b/3.17/wacom_wac.h index d05daed..b3c1a09 100644 --- a/3.17/wacom_wac.h +++ b/3.17/wacom_wac.h @@ -234,7 +234,7 @@ struct wacom_wac { unsigned char data[WACOM_PKGLEN_MAX]; int tool[2]; int id[2]; - __u32 serial[5]; + __u32 serial[2]; bool reporting_data; struct wacom_features features; struct wacom_shared *shared; diff --git a/3.7/wacom.h b/3.7/wacom.h index 5d4361c..2067a5c 100644 --- a/3.7/wacom.h +++ b/3.7/wacom.h @@ -115,6 +115,14 @@ enum wacom_worker { WACOM_WORKER_REMOTE, }; +struct wacom_remote { + spinlock_t remote_lock; + struct kfifo remote_fifo; + struct kobject *remote_dir; + struct attribute_group remote_group[WACOM_MAX_REMOTES]; + __u32 serial[WACOM_MAX_REMOTES]; +}; + struct wacom { dma_addr_t data_dma; struct usb_device *usbdev; @@ -125,8 +133,7 @@ struct wacom { struct work_struct wireless_work; struct work_struct battery_work; struct work_struct remote_work; - spinlock_t remote_lock; - struct kfifo remote_fifo; + struct wacom_remote *remote; bool open; char phys[32]; struct wacom_led { @@ -136,8 +143,6 @@ struct wacom { u8 img_lum; /* OLED matrix display brightness */ } led; struct power_supply battery; - struct kobject *remote_dir; - struct attribute_group remote_group[5]; }; static inline void wacom_schedule_work(struct wacom_wac *wacom_wac, diff --git a/3.7/wacom_sys.c b/3.7/wacom_sys.c index 7afa189..9755952 100644 --- a/3.7/wacom_sys.c +++ b/3.7/wacom_sys.c @@ -1268,19 +1268,16 @@ DEVICE_EKR_ATTR_GROUP(4); static int wacom_remote_create_attr_group(struct wacom *wacom, __u32 serial, int index) { int error = 0; - char *buf; - struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_remote *remote = wacom->remote; - wacom_wac->serial[index] = serial; + remote->serial[index] = serial; - buf = kzalloc(WAC_REMOTE_SERIAL_MAX_STRLEN, GFP_KERNEL); - if (!buf) + remote->remote_group[index].name = kasprintf(GFP_KERNEL, "%d", serial); + if (!remote->remote_group[index].name) return -ENOMEM; - snprintf(buf, WAC_REMOTE_SERIAL_MAX_STRLEN, "%d", serial); - wacom->remote_group[index].name = buf; - error = sysfs_create_group(wacom->remote_dir, - &wacom->remote_group[index]); + error = sysfs_create_group(remote->remote_dir, + &remote->remote_group[index]); if (error) { dev_err(&wacom->intf->dev, "cannot create sysfs group err: %d\n", error); @@ -1292,21 +1289,21 @@ static int wacom_remote_create_attr_group(struct wacom *wacom, __u32 serial, int static void wacom_remote_destroy_attr_group(struct wacom *wacom, __u32 serial) { - struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_remote *remote = wacom->remote; int i; if (!serial) return; for (i = 0; i < WACOM_MAX_REMOTES; i++) { - if (wacom_wac->serial[i] == serial) { - wacom_wac->serial[i] = 0; + if (remote->serial[i] == serial) { + remote->serial[i] = 0; wacom->led.select[i] = WACOM_STATUS_UNKNOWN; - if (wacom->remote_group[i].name) { - sysfs_remove_group(wacom->remote_dir, - &wacom->remote_group[i]); - kfree(wacom->remote_group[i].name); - wacom->remote_group[i].name = NULL; + if (remote->remote_group[i].name) { + sysfs_remove_group(remote->remote_dir, + &remote->remote_group[i]); + kfree((char *)remote->remote_group[i].name); + remote->remote_group[i].name = NULL; } } } @@ -1368,27 +1365,64 @@ static const struct attribute *remote_unpair_attrs[] = { NULL }; -static int wacom_initialize_remote(struct wacom *wacom) +static void wacom_remotes_destroy(struct wacom *wacom) +{ + struct wacom_remote *remote = wacom->remote; + int i; + + if (!remote) + return; + + for (i = 0; i < WACOM_MAX_REMOTES; i++) { + if (wacom->remote->remote_group[i].name) { + wacom_remote_destroy_attr_group(wacom, + wacom->wacom_wac.serial[i]); + } + } + kobject_put(remote->remote_dir); + kfifo_free(&remote->remote_fifo); + wacom->remote = NULL; +} + +static int wacom_initialize_remotes(struct wacom *wacom) { int error = 0; - struct wacom_wac *wacom_wac = &(wacom->wacom_wac); + struct wacom_remote *remote; int i; if (wacom->wacom_wac.features.type != REMOTE) return 0; - wacom->remote_group[0] = remote0_serial_group; - wacom->remote_group[1] = remote1_serial_group; - wacom->remote_group[2] = remote2_serial_group; - wacom->remote_group[3] = remote3_serial_group; - wacom->remote_group[4] = remote4_serial_group; + remote = devm_kzalloc(&wacom->usbdev->dev, sizeof(*wacom->remote), + GFP_KERNEL); + if (!remote) + return -ENOMEM; + + wacom->remote = remote; - wacom->remote_dir = kobject_create_and_add("wacom_remote", - &wacom->intf->dev.kobj); - if (!wacom->remote_dir) + spin_lock_init(&remote->remote_lock); + + error = kfifo_alloc(&remote->remote_fifo, + 5 * sizeof(struct wacom_remote_data), + GFP_KERNEL); + if (error) { + dev_err(&wacom->intf->dev, "failed allocating remote_fifo\n"); + return -ENOMEM; + } + + remote->remote_group[0] = remote0_serial_group; + remote->remote_group[1] = remote1_serial_group; + remote->remote_group[2] = remote2_serial_group; + remote->remote_group[3] = remote3_serial_group; + remote->remote_group[4] = remote4_serial_group; + + remote->remote_dir = kobject_create_and_add("wacom_remote", + &wacom->intf->dev.kobj); + + if (!remote->remote_dir) return -ENOMEM; - error = sysfs_create_files(wacom->remote_dir, remote_unpair_attrs); + error = sysfs_create_files(remote->remote_dir, remote_unpair_attrs); if (error) { dev_err(&wacom->intf->dev, @@ -1398,7 +1432,7 @@ static int wacom_initialize_remote(struct wacom *wacom) for (i = 0; i < WACOM_MAX_REMOTES; i++) { wacom->led.select[i] = WACOM_STATUS_UNKNOWN; - wacom_wac->serial[i] = 0; + remote->serial[i] = 0; } return 0; @@ -1613,58 +1647,58 @@ static void wacom_remote_work(struct work_struct *work) { struct wacom *wacom = container_of(work, struct wacom, remote_work); struct device *dev = &wacom->intf->dev; - struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_remote *remote = wacom->remote; struct wacom_remote_data data; unsigned long flags; unsigned int count; u32 serial; int i, k; - spin_lock_irqsave(&wacom->remote_lock, flags); + spin_lock_irqsave(&remote->remote_lock, flags); - count = kfifo_out(&wacom->remote_fifo, &data, sizeof(data)); + count = kfifo_out(&remote->remote_fifo, &data, sizeof(data)); if (count != sizeof(data)) { dev_err(dev, "workitem triggered without status available\n"); - spin_unlock_irqrestore(&wacom->remote_lock, flags); + spin_unlock_irqrestore(&remote->remote_lock, flags); return; } - if (!kfifo_is_empty(&wacom->remote_fifo)) + if (!kfifo_is_empty(&remote->remote_fifo)) wacom_schedule_work(&wacom->wacom_wac, WACOM_WORKER_REMOTE); - spin_unlock_irqrestore(&wacom->remote_lock, flags); + spin_unlock_irqrestore(&remote->remote_lock, flags); for (i = 0; i < WACOM_MAX_REMOTES; i++) { serial = data.remote[i].serial; if (data.remote[i].connected) { - if (wacom_wac->serial[i] == serial) + if (remote->serial[i] == serial) continue; - if (wacom_wac->serial[i]) { + if (remote->serial[i]) { wacom_remote_destroy_attr_group(wacom, - wacom_wac->serial[i]); + remote->serial[i]); } /* A remote can pair more than once with an EKR, * check to make sure this serial isn't already paired. */ for (k = 0; k < WACOM_MAX_REMOTES; k++) { - if (wacom_wac->serial[k] == serial) + if (remote->serial[k] == serial) break; } if (k < WACOM_MAX_REMOTES) { - wacom_wac->serial[i] = serial; + remote->serial[i] = serial; continue; } wacom_remote_create_attr_group(wacom, serial, i); - } else if (wacom_wac->serial[i]) { + } else if (remote->serial[i]) { wacom_remote_destroy_attr_group(wacom, - wacom_wac->serial[i]); + remote->serial[i]); } } } @@ -1717,16 +1751,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i INIT_WORK(&wacom->wireless_work, wacom_wireless_work); INIT_WORK(&wacom->battery_work, wacom_battery_work); INIT_WORK(&wacom->remote_work, wacom_remote_work); - spin_lock_init(&wacom->remote_lock); - - if (kfifo_alloc(&wacom->remote_fifo, - 5 * sizeof(struct wacom_remote_data), - GFP_KERNEL)) { - dev_err(&wacom->intf->dev, - "%s:failed allocating remote_fifo\n", __func__); - error = -ENOMEM; - goto fail2; - } usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); @@ -1791,7 +1815,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i goto fail4; if (wacom->wacom_wac.features.type == REMOTE) { - error = wacom_initialize_remote(wacom); + error = wacom_initialize_remotes(wacom); if (error) goto fail4; } @@ -1810,7 +1834,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i fail4: wacom_remove_shared_data(wacom_wac); fail3: usb_free_urb(wacom->irq); wacom_destroy_battery(wacom); - kfifo_free(&wacom->remote_fifo); fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); fail1: return error; @@ -1819,7 +1842,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i static void wacom_disconnect(struct usb_interface *intf) { struct wacom *wacom = usb_get_intfdata(intf); - int i; usb_set_intfdata(intf, NULL); @@ -1827,14 +1849,8 @@ static void wacom_disconnect(struct usb_interface *intf) cancel_work_sync(&wacom->wireless_work); cancel_work_sync(&wacom->battery_work); cancel_work_sync(&wacom->remote_work); - kfifo_free(&wacom->remote_fifo); - for (i = 0; i < WACOM_MAX_REMOTES; i++) { - if (wacom->remote_group[i].name) { - wacom_remote_destroy_attr_group(wacom, - wacom->wacom_wac.serial[i]); - } - } - kobject_put(wacom->remote_dir); + + wacom_remotes_destroy(wacom); wacom_unregister_inputs(wacom); wacom_destroy_battery(wacom); usb_free_urb(wacom->irq); diff --git a/3.7/wacom_wac.c b/3.7/wacom_wac.c index 214e0e2..bd6c32a 100644 --- a/3.7/wacom_wac.c +++ b/3.7/wacom_wac.c @@ -703,6 +703,7 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) struct input_dev *input = wacom_wac->input; struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); struct wacom_features *features = &wacom_wac->features; + struct wacom_remote *remote = wacom->remote; int bat_charging, bat_percent, touch_ring_mode; __u32 serial; int i; @@ -756,7 +757,7 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) touch_ring_mode = (data[11] & 0xC0) >> 6; for (i = 0; i < WACOM_MAX_REMOTES; i++) { - if (wacom_wac->serial[i] == serial) + if (remote->serial[i] == serial) wacom->led.select[i] = touch_ring_mode; } @@ -777,6 +778,7 @@ static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); struct device *dev = &wacom->intf->dev; unsigned char *data = wacom_wac->data; + struct wacom_remote *remote = wacom->remote; struct wacom_remote_data remote_data; unsigned long flags; int i, ret; @@ -795,16 +797,16 @@ static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) remote_data.remote[i].connected = connected; } - spin_lock_irqsave(&wacom->remote_lock, flags); + spin_lock_irqsave(&remote->remote_lock, flags); - ret = kfifo_in(&wacom->remote_fifo, &remote_data, sizeof(remote_data)); + ret = kfifo_in(&remote->remote_fifo, &remote_data, sizeof(remote_data)); if (ret != sizeof(remote_data)) { - spin_unlock_irqrestore(&wacom->remote_lock, flags); + spin_unlock_irqrestore(&remote->remote_lock, flags); dev_err(dev, "Can't queue Remote status event.\n"); return; } - spin_unlock_irqrestore(&wacom->remote_lock, flags); + spin_unlock_irqrestore(&remote->remote_lock, flags); wacom_schedule_work(wacom_wac, WACOM_WORKER_REMOTE); } diff --git a/3.7/wacom_wac.h b/3.7/wacom_wac.h index 0ade39c..7e12b8b 100644 --- a/3.7/wacom_wac.h +++ b/3.7/wacom_wac.h @@ -178,7 +178,7 @@ struct wacom_wac { unsigned char *data; int tool[2]; int id[2]; - __u32 serial[5]; + __u32 serial[2]; bool reporting_data; struct wacom_features features; struct wacom_shared *shared; -- 2.7.4 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot _______________________________________________ Linuxwacom-devel mailing list Linuxwacom-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel