* 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:
@@ -26,9 +26,10 @@ public:
|
|||||||
|
|
||||||
status_t InitCheck() const { return fStatus; }
|
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 Open(ProtocolHandler *handler, uint32 flags);
|
||||||
status_t Close(ProtocolHandler *handler);
|
status_t Close(ProtocolHandler *handler);
|
||||||
|
int32 OpenCount() const { return fOpenCount; }
|
||||||
|
|
||||||
void Removed();
|
void Removed();
|
||||||
bool IsRemoved() const { return fRemoved; }
|
bool IsRemoved() const { return fRemoved; }
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <usb/USB_hid.h>
|
#include <usb/USB_hid.h>
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
@@ -26,7 +27,8 @@
|
|||||||
#define RIGHT_ALT_KEY 0x40
|
#define RIGHT_ALT_KEY 0x40
|
||||||
#define ALT_KEYS (LEFT_ALT_KEY | RIGHT_ALT_KEY)
|
#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;
|
static usb_id sDebugKeyboardPipe = 0;
|
||||||
@@ -60,8 +62,11 @@ KeyboardDevice::KeyboardDevice(HIDReport *inputReport, HIDReport *outputReport)
|
|||||||
fLastModifiers(0),
|
fLastModifiers(0),
|
||||||
fCurrentKeys(NULL),
|
fCurrentKeys(NULL),
|
||||||
fLastKeys(NULL),
|
fLastKeys(NULL),
|
||||||
|
fHasReader(0),
|
||||||
fHasDebugReader(false)
|
fHasDebugReader(false)
|
||||||
{
|
{
|
||||||
|
mutex_init(&fLock, "usb keyboard");
|
||||||
|
|
||||||
// find modifiers and keys
|
// find modifiers and keys
|
||||||
for (uint32 i = 0; i < inputReport->CountItems(); i++) {
|
for (uint32 i = 0; i < inputReport->CountItems(); i++) {
|
||||||
HIDReportItem *item = inputReport->ItemAt(i);
|
HIDReportItem *item = inputReport->ItemAt(i);
|
||||||
@@ -145,6 +150,8 @@ KeyboardDevice::~KeyboardDevice()
|
|||||||
remove_debugger_command("get_usb_keyboard_config",
|
remove_debugger_command("get_usb_keyboard_config",
|
||||||
&debug_get_keyboard_config);
|
&debug_get_keyboard_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_destroy(&fLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -209,44 +216,79 @@ KeyboardDevice::Open(uint32 flags, uint32 *cookie)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
fCurrentRepeatDelay = B_INFINITE_TIMEOUT;
|
if (Device()->OpenCount() == 1) {
|
||||||
fCurrentRepeatKey = 0;
|
fCurrentRepeatDelay = B_INFINITE_TIMEOUT;
|
||||||
|
fCurrentRepeatKey = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
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
|
status_t
|
||||||
KeyboardDevice::Control(uint32 *cookie, uint32 op, void *buffer, size_t length)
|
KeyboardDevice::Control(uint32 *cookie, uint32 op, void *buffer, size_t length)
|
||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case KB_READ:
|
case KB_READ:
|
||||||
{
|
{
|
||||||
bigtime_t enterTime = system_time();
|
if (*cookie == 0) {
|
||||||
while (RingBufferReadable() == 0) {
|
if (atomic_or(&fHasReader, 1) != 0)
|
||||||
status_t result = _ReadReport(fCurrentRepeatDelay);
|
return B_BUSY;
|
||||||
if (result != B_OK && result != B_TIMED_OUT)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
if (!Device()->IsOpen())
|
// We're the first, so we become the only reader
|
||||||
return B_ERROR;
|
*cookie = KEYBOARD_FLAG_READER;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// process what is in the ring_buffer, it could be written
|
while (true) {
|
||||||
// there because we handled an interrupt transfer or because
|
MutexLocker locker(fLock);
|
||||||
// we wrote the current repeat key
|
|
||||||
return RingBufferRead(buffer, sizeof(raw_key_info));
|
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:
|
case KB_SET_LEDS:
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "ProtocolHandler.h"
|
#include "ProtocolHandler.h"
|
||||||
|
|
||||||
|
#include <lock.h>
|
||||||
|
|
||||||
|
|
||||||
class HIDReportItem;
|
class HIDReportItem;
|
||||||
|
|
||||||
@@ -27,6 +29,8 @@ public:
|
|||||||
HIDReport *input);
|
HIDReport *input);
|
||||||
|
|
||||||
virtual status_t Open(uint32 flags, uint32 *cookie);
|
virtual status_t Open(uint32 flags, uint32 *cookie);
|
||||||
|
virtual status_t Close(uint32 *cookie);
|
||||||
|
|
||||||
virtual status_t Control(uint32 *cookie, uint32 op, void *buffer,
|
virtual status_t Control(uint32 *cookie, uint32 op, void *buffer,
|
||||||
size_t length);
|
size_t length);
|
||||||
|
|
||||||
@@ -36,6 +40,8 @@ private:
|
|||||||
status_t _ReadReport(bigtime_t timeout);
|
status_t _ReadReport(bigtime_t timeout);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
mutex fLock;
|
||||||
|
|
||||||
HIDReport * fInputReport;
|
HIDReport * fInputReport;
|
||||||
HIDReport * fOutputReport;
|
HIDReport * fOutputReport;
|
||||||
|
|
||||||
@@ -55,6 +61,7 @@ private:
|
|||||||
uint16 * fCurrentKeys;
|
uint16 * fCurrentKeys;
|
||||||
uint16 * fLastKeys;
|
uint16 * fLastKeys;
|
||||||
|
|
||||||
|
int32 fHasReader;
|
||||||
bool fHasDebugReader;
|
bool fHasDebugReader;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user