diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 97e1feffc6e4..62f3c899ab98 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1054,12 +1054,51 @@ static struct input_dev *wacom_allocate_input(struct wacom *wacom) return input_dev; } -static void wacom_unregister_inputs(struct wacom *wacom) +static void wacom_free_inputs(struct wacom *wacom) { - if (wacom->wacom_wac.input) - input_unregister_device(wacom->wacom_wac.input); - if (wacom->wacom_wac.pad_input) - input_unregister_device(wacom->wacom_wac.pad_input); + struct wacom_wac *wacom_wac = &(wacom->wacom_wac); + + if (wacom_wac->input) + input_free_device(wacom_wac->input); + if (wacom_wac->pad_input) + input_free_device(wacom_wac->pad_input); + wacom_wac->input = NULL; + wacom_wac->pad_input = NULL; +} + +static int wacom_allocate_inputs(struct wacom *wacom) +{ + struct input_dev *input_dev, *pad_input_dev; + struct wacom_wac *wacom_wac = &(wacom->wacom_wac); + + input_dev = wacom_allocate_input(wacom); + pad_input_dev = wacom_allocate_input(wacom); + if (!input_dev || !pad_input_dev) { + wacom_free_inputs(wacom); + return -ENOMEM; + } + + wacom_wac->input = input_dev; + wacom_wac->pad_input = pad_input_dev; + wacom_wac->pad_input->name = wacom_wac->pad_name; + + return 0; +} + +static void wacom_clean_inputs(struct wacom *wacom) +{ + if (wacom->wacom_wac.input) { + if (wacom->wacom_wac.input_registered) + input_unregister_device(wacom->wacom_wac.input); + else + input_free_device(wacom->wacom_wac.input); + } + if (wacom->wacom_wac.pad_input) { + if (wacom->wacom_wac.input_registered) + input_unregister_device(wacom->wacom_wac.pad_input); + else + input_free_device(wacom->wacom_wac.pad_input); + } wacom->wacom_wac.input = NULL; wacom->wacom_wac.pad_input = NULL; wacom_destroy_leds(wacom); @@ -1071,24 +1110,19 @@ static int wacom_register_inputs(struct wacom *wacom) struct wacom_wac *wacom_wac = &(wacom->wacom_wac); int error; - input_dev = wacom_allocate_input(wacom); - pad_input_dev = wacom_allocate_input(wacom); - if (!input_dev || !pad_input_dev) { - error = -ENOMEM; - goto fail_allocate_input; - } + input_dev = wacom_wac->input; + pad_input_dev = wacom_wac->pad_input; - wacom_wac->input = input_dev; - wacom_wac->pad_input = pad_input_dev; - wacom_wac->pad_input->name = wacom_wac->pad_name; + if (!input_dev || !pad_input_dev) + return -EINVAL; error = wacom_setup_input_capabilities(input_dev, wacom_wac); if (error) - goto fail_input_cap; + return error; error = input_register_device(input_dev); if (error) - goto fail_register_input; + return error; error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac); if (error) { @@ -1106,6 +1140,8 @@ static int wacom_register_inputs(struct wacom *wacom) goto fail_leds; } + wacom_wac->input_registered = true; + return 0; fail_leds: @@ -1113,16 +1149,7 @@ fail_leds: pad_input_dev = NULL; fail_register_pad_input: input_unregister_device(input_dev); - input_dev = NULL; -fail_register_input: -fail_input_cap: wacom_wac->input = NULL; - wacom_wac->pad_input = NULL; -fail_allocate_input: - if (input_dev) - input_free_device(input_dev); - if (pad_input_dev) - input_free_device(pad_input_dev); return error; } @@ -1147,13 +1174,13 @@ static void wacom_wireless_work(struct work_struct *work) hdev1 = usb_get_intfdata(usbdev->config->interface[1]); wacom1 = hid_get_drvdata(hdev1); wacom_wac1 = &(wacom1->wacom_wac); - wacom_unregister_inputs(wacom1); + wacom_clean_inputs(wacom1); /* Touch interface */ hdev2 = usb_get_intfdata(usbdev->config->interface[2]); wacom2 = hid_get_drvdata(hdev2); wacom_wac2 = &(wacom2->wacom_wac); - wacom_unregister_inputs(wacom2); + wacom_clean_inputs(wacom2); if (wacom_wac->pid == 0) { hid_info(wacom->hdev, "wireless tablet disconnected\n"); @@ -1187,7 +1214,8 @@ static void wacom_wireless_work(struct work_struct *work) wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max; wacom_wac1->shared->type = wacom_wac1->features.type; wacom_wac1->pid = wacom_wac->pid; - error = wacom_register_inputs(wacom1); + error = wacom_allocate_inputs(wacom1) || + wacom_register_inputs(wacom1); if (error) goto fail; @@ -1208,7 +1236,8 @@ static void wacom_wireless_work(struct work_struct *work) snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX, "%s (WL) Pad", wacom_wac2->features.name); wacom_wac2->pid = wacom_wac->pid; - error = wacom_register_inputs(wacom2); + error = wacom_allocate_inputs(wacom2) || + wacom_register_inputs(wacom2); if (error) goto fail; @@ -1225,8 +1254,8 @@ static void wacom_wireless_work(struct work_struct *work) return; fail: - wacom_unregister_inputs(wacom1); - wacom_unregister_inputs(wacom2); + wacom_clean_inputs(wacom1); + wacom_clean_inputs(wacom2); return; } @@ -1400,7 +1429,8 @@ static int wacom_probe(struct hid_device *hdev, } if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) { - error = wacom_register_inputs(wacom); + error = wacom_allocate_inputs(wacom) || + wacom_register_inputs(wacom); if (error) goto fail_register_inputs; } @@ -1434,11 +1464,11 @@ static int wacom_probe(struct hid_device *hdev, return 0; fail_hw_start: - wacom_unregister_inputs(wacom); + wacom_clean_inputs(wacom); if (hdev->bus == BUS_BLUETOOTH) device_remove_file(&hdev->dev, &dev_attr_speed); fail_register_inputs: - wacom_unregister_inputs(wacom); + wacom_clean_inputs(wacom); wacom_destroy_battery(wacom); fail_battery: wacom_remove_shared_data(wacom_wac); @@ -1458,7 +1488,7 @@ static void wacom_remove(struct hid_device *hdev) hid_hw_stop(hdev); cancel_work_sync(&wacom->work); - wacom_unregister_inputs(wacom); + wacom_clean_inputs(wacom); if (hdev->bus == BUS_BLUETOOTH) device_remove_file(&hdev->dev, &dev_attr_speed); wacom_destroy_battery(wacom); diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 339ab5d81a2d..72f9ca8e5cd4 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -167,6 +167,7 @@ struct wacom_wac { struct wacom_shared *shared; struct input_dev *input; struct input_dev *pad_input; + bool input_registered; int pid; int battery_capacity; int num_contacts_left;