* Prepared driver for the implementation of the debugger mode: there is now a

uint32 cookie that is saved per file handle and passed to the ProtocolHandler
  objects.
* Beware that the output of the driver no longer shows the handler as pointer,
  but the internal device cookie.
* Added handling of KB_SET_DEBUG_READER to the KeyboardDevice class (it just
  doesn't do anything with that).
* Cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36274 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2010-04-14 21:59:15 +00:00
parent 1888e2289d
commit 48450caac5
9 changed files with 197 additions and 126 deletions
@@ -1,20 +1,31 @@
/* /*
Driver for USB Human Interface Devices. * Copyright 2008-2009 Michael Lotz <[email protected]>
Copyright (C) 2008-2009 Michael Lotz <[email protected]> * Distributed under the terms of the MIT license.
Distributed under the terms of the MIT license.
*/ */
//! Driver for USB Human Interface Devices.
#include "DeviceList.h" #include "DeviceList.h"
#include "Driver.h" #include "Driver.h"
#include "HIDDevice.h" #include "HIDDevice.h"
#include "ProtocolHandler.h" #include "ProtocolHandler.h"
#include <lock.h> #include <lock.h>
#include <util/AutoLock.h>
#include <new> #include <new>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
struct device_cookie {
ProtocolHandler* handler;
uint32 cookie;
};
int32 api_version = B_CUR_DRIVER_API_VERSION; int32 api_version = B_CUR_DRIVER_API_VERSION;
usb_module_info *gUSBModule = NULL; usb_module_info *gUSBModule = NULL;
DeviceList *gDeviceList = NULL; DeviceList *gDeviceList = NULL;
@@ -163,21 +174,34 @@ usb_hid_device_removed(void *cookie)
static status_t static status_t
usb_hid_open(const char *name, uint32 flags, void **cookie) usb_hid_open(const char *name, uint32 flags, void **_cookie)
{ {
TRACE("open(%s, %lu, %p)\n", name, flags, cookie); TRACE("open(%s, %lu, %p)\n", name, flags, _cookie);
mutex_lock(&sDriverLock);
device_cookie *cookie = new(std::nothrow) device_cookie();
if (cookie == NULL)
return B_NO_MEMORY;
MutexLocker locker(sDriverLock);
ProtocolHandler *handler = (ProtocolHandler *)gDeviceList->FindDevice(name); ProtocolHandler *handler = (ProtocolHandler *)gDeviceList->FindDevice(name);
if (handler == NULL) { TRACE(" name %s: handler %p\n", name, handler);
mutex_unlock(&sDriverLock);
return B_ENTRY_NOT_FOUND; cookie->handler = handler;
cookie->cookie = 0;
status_t result = handler == NULL ? B_ENTRY_NOT_FOUND : B_OK;
if (result == B_OK)
result = handler->Open(flags, &cookie->cookie);
if (result != B_OK) {
delete cookie;
return result;
} }
status_t result = handler->Open(flags); *_cookie = cookie;
*cookie = handler;
mutex_unlock(&sDriverLock); return B_OK;
return result;
} }
@@ -201,30 +225,34 @@ usb_hid_write(void *cookie, off_t position, const void *buffer,
static status_t static status_t
usb_hid_control(void *cookie, uint32 op, void *buffer, size_t length) usb_hid_control(void *_cookie, uint32 op, void *buffer, size_t length)
{ {
device_cookie *cookie = (device_cookie *)_cookie;
TRACE("control(%p, %lu, %p, %lu)\n", cookie, op, buffer, length); TRACE("control(%p, %lu, %p, %lu)\n", cookie, op, buffer, length);
ProtocolHandler *handler = (ProtocolHandler *)cookie; return cookie->handler->Control(&cookie->cookie, op, buffer, length);
return handler->Control(op, buffer, length);
} }
static status_t static status_t
usb_hid_close(void *cookie) usb_hid_close(void *_cookie)
{ {
device_cookie *cookie = (device_cookie *)_cookie;
TRACE("close(%p)\n", cookie); TRACE("close(%p)\n", cookie);
ProtocolHandler *handler = (ProtocolHandler *)cookie; return cookie->handler->Close();
return handler->Close();
} }
static status_t static status_t
usb_hid_free(void *cookie) usb_hid_free(void *_cookie)
{ {
device_cookie *cookie = (device_cookie *)_cookie;
TRACE("free(%p)\n", cookie); TRACE("free(%p)\n", cookie);
mutex_lock(&sDriverLock); mutex_lock(&sDriverLock);
HIDDevice *device = ((ProtocolHandler *)cookie)->Device(); HIDDevice *device = cookie->handler->Device();
if (device->IsOpen()) { if (device->IsOpen()) {
// another handler of this device is still open so we can't free it // another handler of this device is still open so we can't free it
} else if (device->IsRemoved()) { } else if (device->IsRemoved()) {
@@ -242,6 +270,8 @@ usb_hid_free(void *cookie)
} }
mutex_unlock(&sDriverLock); mutex_unlock(&sDriverLock);
delete cookie;
return B_OK; return B_OK;
} }
@@ -1,7 +1,12 @@
/* /*
Copyright (C) 2008-2009 Michael Lotz <[email protected]> * Copyright 2008-2009 Michael Lotz <[email protected]>
Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
*/ */
//! Driver for USB Human Interface Devices.
#include "Driver.h" #include "Driver.h"
#include "HIDDevice.h" #include "HIDDevice.h"
#include "HIDReport.h" #include "HIDReport.h"
@@ -1,17 +1,19 @@
/* /*
Driver for USB Human Interface Devices. * Copyright 2008 Michael Lotz <[email protected]>
Copyright (C) 2008 Michael Lotz <[email protected]> * Distributed under the terms of the MIT license.
Distributed under the terms of the MIT license. */
*/
#ifndef USB_HID_DEVICE_H #ifndef USB_HID_DEVICE_H
#define USB_HID_DEVICE_H #define USB_HID_DEVICE_H
#include "HIDParser.h" #include "HIDParser.h"
#include <USB3.h> #include <USB3.h>
class ProtocolHandler; class ProtocolHandler;
class HIDDevice { class HIDDevice {
public: public:
HIDDevice(usb_device device, HIDDevice(usb_device device,
@@ -19,50 +21,52 @@ public:
size_t interfaceIndex); size_t interfaceIndex);
~HIDDevice(); ~HIDDevice();
void SetParentCookie(int32 cookie); void SetParentCookie(int32 cookie);
int32 ParentCookie() { return fParentCookie; }; int32 ParentCookie() { return fParentCookie; };
status_t InitCheck() { return fStatus; }; status_t InitCheck() { return fStatus; };
bool IsOpen() { return fOpenCount > 0; }; bool IsOpen() { 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);
void Removed(); void Removed();
bool IsRemoved() { return fRemoved; }; bool IsRemoved() { return fRemoved; };
status_t MaybeScheduleTransfer(); status_t MaybeScheduleTransfer();
status_t SendReport(HIDReport *report); status_t SendReport(HIDReport *report);
HIDParser * Parser() { return &fParser; }; HIDParser * Parser() { return &fParser; };
ProtocolHandler * ProtocolHandlerAt(uint32 index); ProtocolHandler * ProtocolHandlerAt(uint32 index);
// only to be used for the kernel debugger information // only to be used for the kernel debugger information
usb_pipe InterruptPipe() { return fInterruptPipe; }; usb_pipe InterruptPipe() { return fInterruptPipe; };
private: private:
static void _TransferCallback(void *cookie, static void _TransferCallback(void *cookie,
status_t status, void *data, status_t status, void *data,
size_t actualLength); size_t actualLength);
status_t fStatus; private:
usb_device fDevice; status_t fStatus;
usb_pipe fInterruptPipe; usb_device fDevice;
size_t fInterfaceIndex; usb_pipe fInterruptPipe;
size_t fInterfaceIndex;
int32 fTransferScheduled; int32 fTransferScheduled;
size_t fTransferBufferSize; size_t fTransferBufferSize;
uint8 * fTransferBuffer; uint8 * fTransferBuffer;
int32 fParentCookie; int32 fParentCookie;
int32 fOpenCount; int32 fOpenCount;
bool fRemoved; bool fRemoved;
HIDParser fParser; HIDParser fParser;
uint32 fProtocolHandlerCount; uint32 fProtocolHandlerCount;
ProtocolHandler ** fProtocolHandlers; ProtocolHandler ** fProtocolHandlers;
}; };
#endif // USB_HID_DEVICE_H #endif // USB_HID_DEVICE_H
@@ -26,6 +26,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
static usb_id sDebugKeyboardPipe = 0; static usb_id sDebugKeyboardPipe = 0;
static size_t sDebugKeyboardReportSize = 0; static size_t sDebugKeyboardReportSize = 0;
@@ -57,7 +59,8 @@ KeyboardDevice::KeyboardDevice(HIDReport *inputReport, HIDReport *outputReport)
fModifierCount(0), fModifierCount(0),
fLastModifiers(0), fLastModifiers(0),
fCurrentKeys(NULL), fCurrentKeys(NULL),
fLastKeys(NULL) fLastKeys(NULL),
fHasDebugReader(false)
{ {
// find modifiers and keys // find modifiers and keys
for (uint32 i = 0; i < inputReport->CountItems(); i++) { for (uint32 i = 0; i < inputReport->CountItems(); i++) {
@@ -197,9 +200,9 @@ KeyboardDevice::AddHandler(HIDDevice *device, HIDReport *input)
status_t status_t
KeyboardDevice::Open(uint32 flags) KeyboardDevice::Open(uint32 flags, uint32 *cookie)
{ {
status_t status = ProtocolHandler::Open(flags); status_t status = ProtocolHandler::Open(flags, cookie);
if (status != B_OK) { if (status != B_OK) {
TRACE_ALWAYS("keyboard device failed to open: %s\n", TRACE_ALWAYS("keyboard device failed to open: %s\n",
strerror(status)); strerror(status));
@@ -213,7 +216,7 @@ KeyboardDevice::Open(uint32 flags)
status_t status_t
KeyboardDevice::Control(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:
@@ -286,6 +289,14 @@ KeyboardDevice::Control(uint32 op, void *buffer, size_t length)
!= B_OK) != B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
return B_OK; return B_OK;
case KB_SET_DEBUG_READER:
if (fHasDebugReader)
return B_BUSY;
*cookie |= KEYBOARD_FLAG_DEBUGGER;
fHasDebugReader = true;
return B_OK;
} }
TRACE_ALWAYS("keyboard device unhandled control 0x%08lx\n", op); TRACE_ALWAYS("keyboard device unhandled control 0x%08lx\n", op);
@@ -1,53 +1,62 @@
/* /*
Copyright (C) 2008-2009 Michael Lotz <[email protected]> * Copyright 2008-2009 Michael Lotz <[email protected]>
Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
*/ */
#ifndef USB_KEYBOARD_DEVICE_H #ifndef USB_KEYBOARD_DEVICE_H
#define USB_KEYBOARD_DEVICE_H #define USB_KEYBOARD_DEVICE_H
#include "ProtocolHandler.h" #include "ProtocolHandler.h"
class HIDReportItem;
#define MAX_MODIFIERS 16 #define MAX_MODIFIERS 16
#define MAX_KEYS 16 #define MAX_KEYS 16
#define MAX_LEDS 3 #define MAX_LEDS 3
class HIDReportItem;
class KeyboardDevice : public ProtocolHandler { class KeyboardDevice : public ProtocolHandler {
public: public:
KeyboardDevice(HIDReport *inputReport, KeyboardDevice(HIDReport *inputReport,
HIDReport *outputReport); HIDReport *outputReport);
virtual ~KeyboardDevice(); virtual ~KeyboardDevice();
static ProtocolHandler * AddHandler(HIDDevice *device, static ProtocolHandler * AddHandler(HIDDevice *device,
HIDReport *input); HIDReport *input);
virtual status_t Open(uint32 flags); virtual status_t Open(uint32 flags, uint32 *cookie);
virtual status_t Control(uint32 op, void *buffer, size_t length); virtual status_t Control(uint32 *cookie, uint32 op, void *buffer,
size_t length);
private: private:
void _WriteKey(uint32 key, bool down); void _WriteKey(uint32 key, bool down);
status_t _SetLEDs(uint8 *data); status_t _SetLEDs(uint8 *data);
status_t _ReadReport(bigtime_t timeout); status_t _ReadReport(bigtime_t timeout);
HIDReport * fInputReport; private:
HIDReport * fOutputReport; HIDReport * fInputReport;
HIDReport * fOutputReport;
HIDReportItem * fModifiers[MAX_MODIFIERS]; HIDReportItem * fModifiers[MAX_MODIFIERS];
HIDReportItem * fKeys[MAX_KEYS]; HIDReportItem * fKeys[MAX_KEYS];
HIDReportItem * fLEDs[MAX_LEDS]; HIDReportItem * fLEDs[MAX_LEDS];
bigtime_t fRepeatDelay; bigtime_t fRepeatDelay;
bigtime_t fRepeatRate; bigtime_t fRepeatRate;
bigtime_t fCurrentRepeatDelay; bigtime_t fCurrentRepeatDelay;
uint32 fCurrentRepeatKey; uint32 fCurrentRepeatKey;
uint32 fKeyCount; uint32 fKeyCount;
uint32 fModifierCount; uint32 fModifierCount;
uint8 fLastModifiers; uint8 fLastModifiers;
uint16 * fCurrentKeys; uint16 * fCurrentKeys;
uint16 * fLastKeys; uint16 * fLastKeys;
bool fHasDebugReader;
}; };
#endif // USB_KEYBOARD_DEVICE_H #endif // USB_KEYBOARD_DEVICE_H
@@ -75,7 +75,7 @@ MouseDevice::AddHandler(HIDDevice *device, HIDReport *report)
status_t status_t
MouseDevice::Control(uint32 op, void *buffer, size_t length) MouseDevice::Control(uint32 *cookie, uint32 op, void *buffer, size_t length)
{ {
switch (op) { switch (op) {
case MS_READ: case MS_READ:
@@ -1,45 +1,51 @@
/* /*
Copyright (C) 2008-2009 Michael Lotz <[email protected]> * Copyright 2008-2009 Michael Lotz <[email protected]>
Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
*/ */
#ifndef USB_MOUSE_DEVICE_H #ifndef USB_MOUSE_DEVICE_H
#define USB_MOUSE_DEVICE_H #define USB_MOUSE_DEVICE_H
#include <InterfaceDefs.h>
#ifndef B_MAX_MOUSE_BUTTONS #include <InterfaceDefs.h>
#define B_MAX_MOUSE_BUTTONS 8
#endif
#include "ProtocolHandler.h" #include "ProtocolHandler.h"
class HIDReportItem; class HIDReportItem;
#ifndef B_MAX_MOUSE_BUTTONS
# define B_MAX_MOUSE_BUTTONS 8
#endif
class MouseDevice : public ProtocolHandler { class MouseDevice : public ProtocolHandler {
public: public:
MouseDevice(HIDReport *report, MouseDevice(HIDReport *report,
HIDReportItem *xAxis, HIDReportItem *yAxis); HIDReportItem *xAxis, HIDReportItem *yAxis);
static ProtocolHandler * AddHandler(HIDDevice *device, static ProtocolHandler * AddHandler(HIDDevice *device,
HIDReport *report); HIDReport *report);
virtual status_t Control(uint32 op, void *buffer, size_t length); virtual status_t Control(uint32 *cookie, uint32 op, void *buffer,
size_t length);
private: private:
status_t _ReadReport(); status_t _ReadReport();
HIDReport * fReport; private:
HIDReport * fReport;
HIDReportItem * fXAxis; HIDReportItem * fXAxis;
HIDReportItem * fYAxis; HIDReportItem * fYAxis;
HIDReportItem * fWheel; HIDReportItem * fWheel;
HIDReportItem * fButtons[B_MAX_MOUSE_BUTTONS]; HIDReportItem * fButtons[B_MAX_MOUSE_BUTTONS];
uint32 fLastButtons; uint32 fLastButtons;
uint32 fClickCount; uint32 fClickCount;
bigtime_t fLastClickTime; bigtime_t fLastClickTime;
bigtime_t fClickSpeed; bigtime_t fClickSpeed;
uint32 fMaxButtons; uint32 fMaxButtons;
}; };
#endif // USB_MOUSE_DEVICE_H #endif // USB_MOUSE_DEVICE_H
@@ -3,6 +3,7 @@
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <ring_buffer.h> #include <ring_buffer.h>
@@ -103,7 +104,7 @@ ProtocolHandler::AddHandlers(HIDDevice *device, ProtocolHandler ***handlerList,
status_t status_t
ProtocolHandler::Open(uint32 flags) ProtocolHandler::Open(uint32 flags, uint32 *cookie)
{ {
return fDevice->Open(this, flags); return fDevice->Open(this, flags);
} }
@@ -117,7 +118,7 @@ ProtocolHandler::Close()
status_t status_t
ProtocolHandler::Control(uint32 op, void *buffer, size_t length) ProtocolHandler::Control(uint32 *cookie, uint32 op, void *buffer, size_t length)
{ {
TRACE_ALWAYS("control on base class\n"); TRACE_ALWAYS("control on base class\n");
return B_ERROR; return B_ERROR;
@@ -5,48 +5,53 @@
#ifndef PROTOCOL_HANDLER_H #ifndef PROTOCOL_HANDLER_H
#define PROTOCOL_HANDLER_H #define PROTOCOL_HANDLER_H
#include <SupportDefs.h> #include <SupportDefs.h>
class HIDDevice; class HIDDevice;
class HIDReport; class HIDReport;
class ProtocolHandler { class ProtocolHandler {
public: public:
ProtocolHandler(HIDDevice *device, ProtocolHandler(HIDDevice *device,
const char *basePath, const char *basePath,
size_t ringBufferSize); size_t ringBufferSize);
virtual ~ProtocolHandler(); virtual ~ProtocolHandler();
status_t InitCheck() { return fStatus; }; status_t InitCheck() { return fStatus; };
HIDDevice * Device() { return fDevice; }; HIDDevice * Device() { return fDevice; };
const char * BasePath() { return fBasePath; }; const char * BasePath() { return fBasePath; };
void SetPublishPath(char *publishPath); void SetPublishPath(char *publishPath);
const char * PublishPath() { return fPublishPath; }; const char * PublishPath() { return fPublishPath; };
static void AddHandlers(HIDDevice *device, static void AddHandlers(HIDDevice *device,
ProtocolHandler ***handlerList, ProtocolHandler ***handlerList,
uint32 *handlerCount); uint32 *handlerCount);
virtual status_t Open(uint32 flags); virtual status_t Open(uint32 flags, uint32 *cookie);
virtual status_t Close(); virtual status_t Close();
virtual status_t Control(uint32 op, void *buffer, size_t length); virtual status_t Control(uint32 *cookie, uint32 op, void *buffer,
size_t length);
int32 RingBufferReadable(); int32 RingBufferReadable();
status_t RingBufferRead(void *buffer, size_t length); status_t RingBufferRead(void *buffer, size_t length);
status_t RingBufferWrite(const void *buffer, status_t RingBufferWrite(const void *buffer,
size_t length); size_t length);
protected: protected:
status_t fStatus; status_t fStatus;
private: private:
HIDDevice * fDevice; HIDDevice * fDevice;
const char * fBasePath; const char * fBasePath;
char * fPublishPath; char * fPublishPath;
struct ring_buffer * fRingBuffer; struct ring_buffer *fRingBuffer;
}; };
#endif // PROTOCOL_HANDLER_H #endif // PROTOCOL_HANDLER_H