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
This commit is contained in:
Stephan Aßmus
2008-10-29 21:23:19 +00:00
parent 7ea4cf085e
commit 9d42ec70c9
3 changed files with 36 additions and 7 deletions
@@ -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)
@@ -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;
@@ -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: