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: