From 9d42ec70c9c66bf40fa1e7e411e1fc7fa72e40a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Wed, 29 Oct 2008 21:23:19 +0000 Subject: [PATCH] Several problems prevented USB HIDs to be opened, closed and reopened: * The first problem was introduced by myself, when I added deleting the transfer semaphore in HIDDevice::Close(). Obviously, I should (re)create it in Open() then, or it won't work another time. (Open() is now the only place where it's created.) * The second problem was when transfers have already been scheduled the last time the device was open, but never triggered yet. We need to reset the fTransferUnprocessed flag, or we won't schedule another transfer but wait on the transfer semaphore anyways in Control(). I also added canceling the usb transfers with the stack in Close(). * The remaining problems were specific to the KeyboardDevice, the repeat key stuff needs to be reset in Open(). I also added unsetting the repeat key when the key release is detected, but this should have already worked, because the semaphore timeout was reset to B_INFINITE_TIMEOUT. One can now "/system/servers/input_server -q" and everything will be back in working order. There may be some remaining problems in the Wacom driver which I have not yet looked at. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28368 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../drivers/input/usb_hid/HIDDevice.cpp | 20 ++++++++++++----- .../drivers/input/usb_hid/KeyboardDevice.cpp | 22 ++++++++++++++++++- .../drivers/input/usb_hid/KeyboardDevice.h | 1 + 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp b/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp index 4fb955cfa1..139082c704 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp @@ -39,12 +39,6 @@ HIDDevice::HIDDevice(usb_device device, usb_pipe interruptPipe, if (ringBufferSize > 0) fRingBuffer = create_ring_buffer(ringBufferSize); - fTransferNotifySem = create_sem(0, "hid device transfer notify sem"); - if (fTransferNotifySem < B_OK) { - fStatus = fTransferNotifySem; - return; - } - fTransferBuffer = (uint8 *)malloc(fTotalReportSize); if (fTransferBuffer == NULL) { fStatus = B_NO_MEMORY; @@ -231,7 +225,17 @@ HIDDevice::SetParentCookie(int32 cookie) status_t HIDDevice::Open(uint32 flags) { + if (fOpen) + return B_BUSY; + + if (fTransferNotifySem < 0) { + fTransferNotifySem = create_sem(0, "hid device transfer notify sem"); + if (fTransferNotifySem < 0) + return (status_t)fTransferNotifySem; + } + fOpen = true; + return B_OK; } @@ -242,8 +246,10 @@ HIDDevice::Close() fOpen = false; // make threads waiting for a transfer bail out if (fTransferNotifySem >= 0) { + gUSBModule->cancel_queued_transfers(fInterruptPipe); delete_sem(fTransferNotifySem); fTransferNotifySem = -1; + _SetTransferProcessed(); } return B_OK; } @@ -307,6 +313,8 @@ HIDDevice::_IsTransferUnprocessed() status_t HIDDevice::_ScheduleTransfer() { + if (fTransferNotifySem < 0) + return B_ERROR; if (fTransferUnprocessed) return B_BUSY; if (fRemoved) diff --git a/src/add-ons/kernel/drivers/input/usb_hid/KeyboardDevice.cpp b/src/add-ons/kernel/drivers/input/usb_hid/KeyboardDevice.cpp index 170042c803..4cf9d0cb3f 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/KeyboardDevice.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/KeyboardDevice.cpp @@ -43,6 +43,23 @@ KeyboardDevice::~KeyboardDevice() } +status_t +KeyboardDevice::Open(uint32 flags) +{ + status_t status = HIDDevice::Open(flags); + if (status != B_OK) { + TRACE_ALWAYS("keyboard device failed to open: %s\n", + strerror(status)); + return status; + } + + fCurrentRepeatDelay = B_INFINITE_TIMEOUT; + fCurrentRepeatKey = 0; + + return B_OK; +} + + status_t KeyboardDevice::Control(uint32 op, void *buffer, size_t length) { @@ -71,6 +88,7 @@ KeyboardDevice::Control(uint32 op, void *buffer, size_t length) _WriteKey(fCurrentRepeatKey, true); // the next timeout is reduced to the repeat_rate fCurrentRepeatDelay = fRepeatRate; + break; } else if (result == B_INTERRUPTED && IsOpen()) { continue; } else @@ -346,8 +364,10 @@ KeyboardDevice::_InterpretBuffer() fCurrentRepeatDelay = fRepeatDelay; } else { // cancel the repeats if they are for this key - if (fCurrentRepeatKey == key) + if (fCurrentRepeatKey == key) { fCurrentRepeatDelay = B_INFINITE_TIMEOUT; + fCurrentRepeatKey = 0; + } } } else break; diff --git a/src/add-ons/kernel/drivers/input/usb_hid/KeyboardDevice.h b/src/add-ons/kernel/drivers/input/usb_hid/KeyboardDevice.h index 620f2cf112..d4f084863c 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/KeyboardDevice.h +++ b/src/add-ons/kernel/drivers/input/usb_hid/KeyboardDevice.h @@ -18,6 +18,7 @@ public: size_t totalReportSize); virtual ~KeyboardDevice(); +virtual status_t Open(uint32 flags); virtual status_t Control(uint32 op, void *buffer, size_t length); private: