aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2022-03-23 22:39:07 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2022-03-24 11:30:47 +0200
commit3865f5c94cb90d16810b7e751fa79034321ea836 (patch)
tree67f44fc695189ae3ac28a931b6856991535167fe
parentfed8081d45d05ecf2b557515e17a5005b90a7e96 (diff)
downloadhid-tmff2-3865f5c94cb90d16810b7e751fa79034321ea836.tar.gz
hid-tmff2-3865f5c94cb90d16810b7e751fa79034321ea836.zip
fixed possible kernel oops when unplugging device
-rw-r--r--hid-tmff2.c9
-rw-r--r--hid-tmff2.h4
-rw-r--r--hid-tmt248.c16
-rw-r--r--hid-tmt300rs.c12
4 files changed, 24 insertions, 17 deletions
diff --git a/hid-tmff2.c b/hid-tmff2.c
index 4aa6141..d632b09 100644
--- a/hid-tmff2.c
+++ b/hid-tmff2.c
@@ -408,7 +408,7 @@ static void tmff2_close(struct input_dev *dev)
return;
if (tmff2->close) {
- tmff2->close(tmff2->data);
+ tmff2->close(tmff2->data, tmff2->hdev != 0);
return;
}
@@ -524,6 +524,7 @@ static int tmff2_wheel_init(struct tmff2_device_entry *tmff2)
return 0;
+ input_ff_destroy(tmff2->input_dev);
err:
return ret;
}
@@ -611,7 +612,6 @@ static void tmff2_remove(struct hid_device *hdev)
if (!tmff2)
return;
-
cancel_delayed_work_sync(&tmff2->work);
dev = &tmff2->hdev->dev;
@@ -627,8 +627,11 @@ static void tmff2_remove(struct hid_device *hdev)
if (tmff2->params & PARAM_ALT_MODE)
device_remove_file(dev, &dev_attr_alt_mode);
- tmff2->wheel_destroy(tmff2->data);
+ /* indicate that the underlying usb device should not be assumed to be
+ * accessible */
+ tmff2->hdev = 0;
hid_hw_stop(hdev);
+ tmff2->wheel_destroy(tmff2->data);
kfree(tmff2->states);
kfree(tmff2);
diff --git a/hid-tmff2.h b/hid-tmff2.h
index b396d78..4058cf7 100644
--- a/hid-tmff2.h
+++ b/hid-tmff2.h
@@ -79,7 +79,7 @@ struct tmff2_device_entry {
/* optional callbacks */
int (*open)(void *data);
- int (*close)(void *data);
+ int (*close)(void *data, int dev_accessible);
int (*set_gain)(void *data, uint16_t gain);
int (*set_range)(void *data, uint16_t range);
int (*switch_mode)(void *data, uint16_t mode);
@@ -123,7 +123,7 @@ int t300rs_update_effect(void *, struct tmff2_effect_state *);
int t300rs_stop_effect(void *, struct tmff2_effect_state *);
int t300rs_open(void *);
-int t300rs_close(void *);
+int t300rs_close(void *, int);
int t300rs_set_gain(void *, uint16_t);
int t300rs_set_range(void *, uint16_t);
int t300rs_set_autocenter(void *, uint16_t);
diff --git a/hid-tmt248.c b/hid-tmt248.c
index f3d4700..839f670 100644
--- a/hid-tmt248.c
+++ b/hid-tmt248.c
@@ -254,19 +254,21 @@ static int t248_open(void *data)
return t248->open(t248->input_dev);
}
-static int t248_close(void *data)
+static int t248_close(void *data, int dev_accessible)
{
struct t300rs_device_entry *t248 = data;
if (!t248)
return -ENODEV;
- t248->send_buffer[0] = 0x01;
- t248->send_buffer[1] = 0x05;
- t300rs_send_int(t248);
+ if (dev_accessible) {
+ t248->send_buffer[0] = 0x01;
+ t248->send_buffer[1] = 0x05;
+ t300rs_send_int(t248);
- t248->send_buffer[0] = 0x01;
- t248->send_buffer[1] = 0x00;
- t300rs_send_int(t248);
+ t248->send_buffer[0] = 0x01;
+ t248->send_buffer[1] = 0x00;
+ t300rs_send_int(t248);
+ }
t248->close(t248->input_dev);
return 0;
diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c
index 167262c..c2a6c64 100644
--- a/hid-tmt300rs.c
+++ b/hid-tmt300rs.c
@@ -1303,7 +1303,7 @@ int t300rs_open(void *data)
return t300rs->open(t300rs->input_dev);
}
-int t300rs_close(void *data)
+int t300rs_close(void *data, int dev_accessible)
{
struct t300rs_device_entry *t300rs = data;
struct t300rs_packet_close {
@@ -1314,11 +1314,13 @@ int t300rs_close(void *data)
if (!t300rs)
return -ENODEV;
- close_packet = (struct t300rs_packet_close *)t300rs->send_buffer;
- close_packet->header.cmd = 0x01;
+ if (dev_accessible) {
+ close_packet = (struct t300rs_packet_close *)t300rs->send_buffer;
+ close_packet->header.cmd = 0x01;
- if ((ret = t300rs_send_int(t300rs)))
- hid_warn(t300rs->hdev, "failed sending close command\n");
+ if ((ret = t300rs_send_int(t300rs)))
+ hid_warn(t300rs->hdev, "failed sending close command\n");
+ }
t300rs->close(t300rs->input_dev);
return ret;