* Implemented the debugger mode for the USB keyboard driver.
* Made the USB keyboard driver safe to be used from more than one team - only the first one will be able to retrieve any keys. Before, since there was no locking, internal structures would have been messed up in that case. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36283 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d5009951b7
commit
7380abeb44
@ -26,9 +26,10 @@ public:
|
||||
|
||||
status_t InitCheck() const { return fStatus; }
|
||||
|
||||
bool IsOpen() const { return fOpenCount > 0; };
|
||||
bool IsOpen() const { return fOpenCount > 0; }
|
||||
status_t Open(ProtocolHandler *handler, uint32 flags);
|
||||
status_t Close(ProtocolHandler *handler);
|
||||
int32 OpenCount() const { return fOpenCount; }
|
||||
|
||||
void Removed();
|
||||
bool IsRemoved() const { return fRemoved; }
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <usb/USB_hid.h>
|
||||
#include <util/AutoLock.h>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
@ -26,7 +27,8 @@
|
||||
#define RIGHT_ALT_KEY 0x40
|
||||
#define ALT_KEYS (LEFT_ALT_KEY | RIGHT_ALT_KEY)
|
||||
|
||||
#define KEYBOARD_FLAG_DEBUGGER 0x01
|
||||
#define KEYBOARD_FLAG_READER 0x01
|
||||
#define KEYBOARD_FLAG_DEBUGGER 0x02
|
||||
|
||||
|
||||
static usb_id sDebugKeyboardPipe = 0;
|
||||
@ -60,8 +62,11 @@ KeyboardDevice::KeyboardDevice(HIDReport *inputReport, HIDReport *outputReport)
|
||||
fLastModifiers(0),
|
||||
fCurrentKeys(NULL),
|
||||
fLastKeys(NULL),
|
||||
fHasReader(0),
|
||||
fHasDebugReader(false)
|
||||
{
|
||||
mutex_init(&fLock, "usb keyboard");
|
||||
|
||||
// find modifiers and keys
|
||||
for (uint32 i = 0; i < inputReport->CountItems(); i++) {
|
||||
HIDReportItem *item = inputReport->ItemAt(i);
|
||||
@ -145,6 +150,8 @@ KeyboardDevice::~KeyboardDevice()
|
||||
remove_debugger_command("get_usb_keyboard_config",
|
||||
&debug_get_keyboard_config);
|
||||
}
|
||||
|
||||
mutex_destroy(&fLock);
|
||||
}
|
||||
|
||||
|
||||
@ -209,44 +216,79 @@ KeyboardDevice::Open(uint32 flags, uint32 *cookie)
|
||||
return status;
|
||||
}
|
||||
|
||||
fCurrentRepeatDelay = B_INFINITE_TIMEOUT;
|
||||
fCurrentRepeatKey = 0;
|
||||
if (Device()->OpenCount() == 1) {
|
||||
fCurrentRepeatDelay = B_INFINITE_TIMEOUT;
|
||||
fCurrentRepeatKey = 0;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
KeyboardDevice::Close(uint32 *cookie)
|
||||
{
|
||||
if ((*cookie & KEYBOARD_FLAG_DEBUGGER) != 0)
|
||||
fHasDebugReader = false;
|
||||
if ((*cookie & KEYBOARD_FLAG_READER) != 0)
|
||||
atomic_and(&fHasReader, 0);
|
||||
|
||||
return ProtocolHandler::Close(cookie);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
KeyboardDevice::Control(uint32 *cookie, uint32 op, void *buffer, size_t length)
|
||||
{
|
||||
switch (op) {
|
||||
case KB_READ:
|
||||
{
|
||||
bigtime_t enterTime = system_time();
|
||||
while (RingBufferReadable() == 0) {
|
||||
status_t result = _ReadReport(fCurrentRepeatDelay);
|
||||
if (result != B_OK && result != B_TIMED_OUT)
|
||||
return result;
|
||||
if (*cookie == 0) {
|
||||
if (atomic_or(&fHasReader, 1) != 0)
|
||||
return B_BUSY;
|
||||
|
||||
if (!Device()->IsOpen())
|
||||
return B_ERROR;
|
||||
|
||||
if (RingBufferReadable() == 0 && fCurrentRepeatKey != 0
|
||||
&& system_time() - enterTime > fCurrentRepeatDelay) {
|
||||
// this case is for handling key repeats, it means no
|
||||
// interrupt transfer has happened or it didn't produce any
|
||||
// new key events, but a repeated key down is due
|
||||
_WriteKey(fCurrentRepeatKey, true);
|
||||
|
||||
// the next timeout is reduced to the repeat_rate
|
||||
fCurrentRepeatDelay = fRepeatRate;
|
||||
break;
|
||||
}
|
||||
// We're the first, so we become the only reader
|
||||
*cookie = KEYBOARD_FLAG_READER;
|
||||
}
|
||||
|
||||
// process what is in the ring_buffer, it could be written
|
||||
// there because we handled an interrupt transfer or because
|
||||
// we wrote the current repeat key
|
||||
return RingBufferRead(buffer, sizeof(raw_key_info));
|
||||
while (true) {
|
||||
MutexLocker locker(fLock);
|
||||
|
||||
bigtime_t enterTime = system_time();
|
||||
while (RingBufferReadable() == 0) {
|
||||
status_t result = _ReadReport(fCurrentRepeatDelay);
|
||||
if (result != B_OK && result != B_TIMED_OUT)
|
||||
return result;
|
||||
|
||||
if (!Device()->IsOpen())
|
||||
return B_ERROR;
|
||||
|
||||
if (RingBufferReadable() == 0 && fCurrentRepeatKey != 0
|
||||
&& system_time() - enterTime > fCurrentRepeatDelay) {
|
||||
// this case is for handling key repeats, it means no
|
||||
// interrupt transfer has happened or it didn't produce any
|
||||
// new key events, but a repeated key down is due
|
||||
_WriteKey(fCurrentRepeatKey, true);
|
||||
|
||||
// the next timeout is reduced to the repeat_rate
|
||||
fCurrentRepeatDelay = fRepeatRate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fHasDebugReader && (*cookie & KEYBOARD_FLAG_DEBUGGER)
|
||||
== 0) {
|
||||
// Handover buffer to the debugger instead
|
||||
locker.Unlock();
|
||||
snooze(25000);
|
||||
continue;
|
||||
}
|
||||
|
||||
// process what is in the ring_buffer, it could be written
|
||||
// there because we handled an interrupt transfer or because
|
||||
// we wrote the current repeat key
|
||||
return RingBufferRead(buffer, sizeof(raw_key_info));
|
||||
}
|
||||
}
|
||||
|
||||
case KB_SET_LEDS:
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include "ProtocolHandler.h"
|
||||
|
||||
#include <lock.h>
|
||||
|
||||
|
||||
class HIDReportItem;
|
||||
|
||||
@ -27,6 +29,8 @@ public:
|
||||
HIDReport *input);
|
||||
|
||||
virtual status_t Open(uint32 flags, uint32 *cookie);
|
||||
virtual status_t Close(uint32 *cookie);
|
||||
|
||||
virtual status_t Control(uint32 *cookie, uint32 op, void *buffer,
|
||||
size_t length);
|
||||
|
||||
@ -36,6 +40,8 @@ private:
|
||||
status_t _ReadReport(bigtime_t timeout);
|
||||
|
||||
private:
|
||||
mutex fLock;
|
||||
|
||||
HIDReport * fInputReport;
|
||||
HIDReport * fOutputReport;
|
||||
|
||||
@ -55,6 +61,7 @@ private:
|
||||
uint16 * fCurrentKeys;
|
||||
uint16 * fLastKeys;
|
||||
|
||||
int32 fHasReader;
|
||||
bool fHasDebugReader;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user