diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2008-11-01 18:41:46 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2008-11-13 04:31:36 -0500 |
commit | e3e14de50dff86331b8f0d701e910146c0049bf5 (patch) | |
tree | b6878bf88a22d12e0cad3fec63e5ccfa7217f921 /drivers/hid | |
parent | 43ff3a48c13f3ddc085271c2eea2985d28c8aa08 (diff) |
HID: fix start/stop cycle in usbhid driver
`stop' left out usbhid->urb* pointers and so the next `start' thought
it needs to allocate nothing and used the memory pointers previously
pointed to. This led to memory corruption and device malfunction.
Also don't forget to clear disconnect flag on start which was left set
by the previous `stop'.
This fixes
echo DEVICE > /sys/bus/hid/drivers/DRIVER/unbind
echo DEVICE > /sys/bus/hid/drivers/DRIVER/bind
failures.
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 18e5ddd722cd..f0339aefc798 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -781,6 +781,8 @@ static int usbhid_start(struct hid_device *hid) | |||
781 | unsigned int n, insize = 0; | 781 | unsigned int n, insize = 0; |
782 | int ret; | 782 | int ret; |
783 | 783 | ||
784 | clear_bit(HID_DISCONNECTED, &usbhid->iofl); | ||
785 | |||
784 | usbhid->bufsize = HID_MIN_BUFFER_SIZE; | 786 | usbhid->bufsize = HID_MIN_BUFFER_SIZE; |
785 | hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); | 787 | hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); |
786 | hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); | 788 | hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); |
@@ -888,6 +890,9 @@ fail: | |||
888 | usb_free_urb(usbhid->urbin); | 890 | usb_free_urb(usbhid->urbin); |
889 | usb_free_urb(usbhid->urbout); | 891 | usb_free_urb(usbhid->urbout); |
890 | usb_free_urb(usbhid->urbctrl); | 892 | usb_free_urb(usbhid->urbctrl); |
893 | usbhid->urbin = NULL; | ||
894 | usbhid->urbout = NULL; | ||
895 | usbhid->urbctrl = NULL; | ||
891 | hid_free_buffers(dev, hid); | 896 | hid_free_buffers(dev, hid); |
892 | mutex_unlock(&usbhid->setup); | 897 | mutex_unlock(&usbhid->setup); |
893 | return ret; | 898 | return ret; |
@@ -924,6 +929,9 @@ static void usbhid_stop(struct hid_device *hid) | |||
924 | usb_free_urb(usbhid->urbin); | 929 | usb_free_urb(usbhid->urbin); |
925 | usb_free_urb(usbhid->urbctrl); | 930 | usb_free_urb(usbhid->urbctrl); |
926 | usb_free_urb(usbhid->urbout); | 931 | usb_free_urb(usbhid->urbout); |
932 | usbhid->urbin = NULL; /* don't mess up next start */ | ||
933 | usbhid->urbctrl = NULL; | ||
934 | usbhid->urbout = NULL; | ||
927 | 935 | ||
928 | hid_free_buffers(hid_to_usb_dev(hid), hid); | 936 | hid_free_buffers(hid_to_usb_dev(hid), hid); |
929 | mutex_unlock(&usbhid->setup); | 937 | mutex_unlock(&usbhid->setup); |