* 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

View File

@ -1,20 +1,31 @@
/*
Driver for USB Human Interface Devices.
Copyright (C) 2008-2009 Michael Lotz <mmlr@mlotz.ch>
Distributed under the terms of the MIT license.
* Copyright 2008-2009 Michael Lotz <mmlr@mlotz.ch>
* Distributed under the terms of the MIT license.
*/
//! Driver for USB Human Interface Devices.
#include "DeviceList.h"
#include "Driver.h"
#include "HIDDevice.h"
#include "ProtocolHandler.h"
#include <lock.h>
#include <util/AutoLock.h>
#include <new>
#include <stdio.h>
#include <string.h>
struct device_cookie {
ProtocolHandler* handler;
uint32 cookie;
};
int32 api_version = B_CUR_DRIVER_API_VERSION;
usb_module_info *gUSBModule = NULL;
DeviceList *gDeviceList = NULL;
@ -163,21 +174,34 @@ usb_hid_device_removed(void *cookie)
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);
mutex_lock(&sDriverLock);
TRACE("open(%s, %lu, %p)\n", name, flags, _cookie);
device_cookie *cookie = new(std::nothrow) device_cookie();
if (cookie == NULL)
return B_NO_MEMORY;
MutexLocker locker(sDriverLock);
ProtocolHandler *handler = (ProtocolHandler *)gDeviceList->FindDevice(name);
if (handler == NULL) {
mutex_unlock(&sDriverLock);
return B_ENTRY_NOT_FOUND;
TRACE(" name %s: handler %p\n", name, handler);
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 = handler;
mutex_unlock(&sDriverLock);
return result;
*_cookie = cookie;
return B_OK;
}
@ -201,30 +225,34 @@ usb_hid_write(void *cookie, off_t position, const void *buffer,
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);
ProtocolHandler *handler = (ProtocolHandler *)cookie;
return handler->Control(op, buffer, length);
return cookie->handler->Control(&cookie->cookie, op, buffer, length);
}
static status_t
usb_hid_close(void *cookie)
usb_hid_close(void *_cookie)
{
device_cookie *cookie = (device_cookie *)_cookie;
TRACE("close(%p)\n", cookie);
ProtocolHandler *handler = (ProtocolHandler *)cookie;
return handler->Close();
return cookie->handler->Close();
}
static status_t
usb_hid_free(void *cookie)
usb_hid_free(void *_cookie)
{
device_cookie *cookie = (device_cookie *)_cookie;
TRACE("free(%p)\n", cookie);
mutex_lock(&sDriverLock);
HIDDevice *device = ((ProtocolHandler *)cookie)->Device();
HIDDevice *device = cookie->handler->Device();
if (device->IsOpen()) {
// another handler of this device is still open so we can't free it
} else if (device->IsRemoved()) {
@ -242,6 +270,8 @@ usb_hid_free(void *cookie)
}
mutex_unlock(&sDriverLock);
delete cookie;
return B_OK;
}

View File

@ -1,7 +1,12 @@
/*
Copyright (C) 2008-2009 Michael Lotz <mmlr@mlotz.ch>
Distributed under the terms of the MIT license.
*/
* Copyright 2008-2009 Michael Lotz <mmlr@mlotz.ch>
* Distributed under the terms of the MIT license.
*/
//! Driver for USB Human Interface Devices.
#include "Driver.h"
#include "HIDDevice.h"
#include "HIDReport.h"

View File

@ -1,17 +1,19 @@
/*
Driver for USB Human Interface Devices.
Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
Distributed under the terms of the MIT license.
*/
* Copyright 2008 Michael Lotz <mmlr@mlotz.ch>
* Distributed under the terms of the MIT license.
*/
#ifndef USB_HID_DEVICE_H
#define USB_HID_DEVICE_H
#include "HIDParser.h"
#include <USB3.h>
class ProtocolHandler;
class HIDDevice {
public:
HIDDevice(usb_device device,
@ -19,50 +21,52 @@ public:
size_t interfaceIndex);
~HIDDevice();
void SetParentCookie(int32 cookie);
int32 ParentCookie() { return fParentCookie; };
void SetParentCookie(int32 cookie);
int32 ParentCookie() { return fParentCookie; };
status_t InitCheck() { return fStatus; };
status_t InitCheck() { return fStatus; };
bool IsOpen() { return fOpenCount > 0; };
status_t Open(ProtocolHandler *handler, uint32 flags);
status_t Close(ProtocolHandler *handler);
bool IsOpen() { return fOpenCount > 0; };
status_t Open(ProtocolHandler *handler, uint32 flags);
status_t Close(ProtocolHandler *handler);
void Removed();
bool IsRemoved() { return fRemoved; };
void Removed();
bool IsRemoved() { return fRemoved; };
status_t MaybeScheduleTransfer();
status_t MaybeScheduleTransfer();
status_t SendReport(HIDReport *report);
status_t SendReport(HIDReport *report);
HIDParser * Parser() { return &fParser; };
ProtocolHandler * ProtocolHandlerAt(uint32 index);
HIDParser * Parser() { return &fParser; };
ProtocolHandler * ProtocolHandlerAt(uint32 index);
// only to be used for the kernel debugger information
usb_pipe InterruptPipe() { return fInterruptPipe; };
// only to be used for the kernel debugger information
usb_pipe InterruptPipe() { return fInterruptPipe; };
private:
static void _TransferCallback(void *cookie,
static void _TransferCallback(void *cookie,
status_t status, void *data,
size_t actualLength);
status_t fStatus;
usb_device fDevice;
usb_pipe fInterruptPipe;
size_t fInterfaceIndex;
private:
status_t fStatus;
usb_device fDevice;
usb_pipe fInterruptPipe;
size_t fInterfaceIndex;
int32 fTransferScheduled;
size_t fTransferBufferSize;
uint8 * fTransferBuffer;
int32 fTransferScheduled;
size_t fTransferBufferSize;
uint8 * fTransferBuffer;
int32 fParentCookie;
int32 fOpenCount;
bool fRemoved;
int32 fParentCookie;
int32 fOpenCount;
bool fRemoved;
HIDParser fParser;
HIDParser fParser;
uint32 fProtocolHandlerCount;
ProtocolHandler ** fProtocolHandlers;
uint32 fProtocolHandlerCount;
ProtocolHandler ** fProtocolHandlers;
};
#endif // USB_HID_DEVICE_H

View File

@ -26,6 +26,8 @@
#define RIGHT_ALT_KEY 0x40
#define ALT_KEYS (LEFT_ALT_KEY | RIGHT_ALT_KEY)
#define KEYBOARD_FLAG_DEBUGGER 0x01
static usb_id sDebugKeyboardPipe = 0;
static size_t sDebugKeyboardReportSize = 0;
@ -57,7 +59,8 @@ KeyboardDevice::KeyboardDevice(HIDReport *inputReport, HIDReport *outputReport)
fModifierCount(0),
fLastModifiers(0),
fCurrentKeys(NULL),
fLastKeys(NULL)
fLastKeys(NULL),
fHasDebugReader(false)
{
// find modifiers and keys
for (uint32 i = 0; i < inputReport->CountItems(); i++) {
@ -197,9 +200,9 @@ KeyboardDevice::AddHandler(HIDDevice *device, HIDReport *input)
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) {
TRACE_ALWAYS("keyboard device failed to open: %s\n",
strerror(status));
@ -213,7 +216,7 @@ KeyboardDevice::Open(uint32 flags)
status_t
KeyboardDevice::Control(uint32 op, void *buffer, size_t length)
KeyboardDevice::Control(uint32 *cookie, uint32 op, void *buffer, size_t length)
{
switch (op) {
case KB_READ:
@ -286,6 +289,14 @@ KeyboardDevice::Control(uint32 op, void *buffer, size_t length)
!= B_OK)
return B_BAD_ADDRESS;
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);

View File

@ -1,53 +1,62 @@
/*
Copyright (C) 2008-2009 Michael Lotz <mmlr@mlotz.ch>
Distributed under the terms of the MIT license.
*/
* Copyright 2008-2009 Michael Lotz <mmlr@mlotz.ch>
* Distributed under the terms of the MIT license.
*/
#ifndef USB_KEYBOARD_DEVICE_H
#define USB_KEYBOARD_DEVICE_H
#include "ProtocolHandler.h"
class HIDReportItem;
#define MAX_MODIFIERS 16
#define MAX_KEYS 16
#define MAX_LEDS 3
class HIDReportItem;
class KeyboardDevice : public ProtocolHandler {
public:
KeyboardDevice(HIDReport *inputReport,
HIDReport *outputReport);
virtual ~KeyboardDevice();
virtual ~KeyboardDevice();
static ProtocolHandler * AddHandler(HIDDevice *device,
static ProtocolHandler * AddHandler(HIDDevice *device,
HIDReport *input);
virtual status_t Open(uint32 flags);
virtual status_t Control(uint32 op, void *buffer, size_t length);
virtual status_t Open(uint32 flags, uint32 *cookie);
virtual status_t Control(uint32 *cookie, uint32 op, void *buffer,
size_t length);
private:
void _WriteKey(uint32 key, bool down);
status_t _SetLEDs(uint8 *data);
status_t _ReadReport(bigtime_t timeout);
void _WriteKey(uint32 key, bool down);
status_t _SetLEDs(uint8 *data);
status_t _ReadReport(bigtime_t timeout);
HIDReport * fInputReport;
HIDReport * fOutputReport;
private:
HIDReport * fInputReport;
HIDReport * fOutputReport;
HIDReportItem * fModifiers[MAX_MODIFIERS];
HIDReportItem * fKeys[MAX_KEYS];
HIDReportItem * fLEDs[MAX_LEDS];
HIDReportItem * fModifiers[MAX_MODIFIERS];
HIDReportItem * fKeys[MAX_KEYS];
HIDReportItem * fLEDs[MAX_LEDS];
bigtime_t fRepeatDelay;
bigtime_t fRepeatRate;
bigtime_t fCurrentRepeatDelay;
uint32 fCurrentRepeatKey;
bigtime_t fRepeatDelay;
bigtime_t fRepeatRate;
bigtime_t fCurrentRepeatDelay;
uint32 fCurrentRepeatKey;
uint32 fKeyCount;
uint32 fModifierCount;
uint32 fKeyCount;
uint32 fModifierCount;
uint8 fLastModifiers;
uint16 * fCurrentKeys;
uint16 * fLastKeys;
uint8 fLastModifiers;
uint16 * fCurrentKeys;
uint16 * fLastKeys;
bool fHasDebugReader;
};
#endif // USB_KEYBOARD_DEVICE_H

View File

@ -75,7 +75,7 @@ MouseDevice::AddHandler(HIDDevice *device, HIDReport *report)
status_t
MouseDevice::Control(uint32 op, void *buffer, size_t length)
MouseDevice::Control(uint32 *cookie, uint32 op, void *buffer, size_t length)
{
switch (op) {
case MS_READ:

View File

@ -1,45 +1,51 @@
/*
Copyright (C) 2008-2009 Michael Lotz <mmlr@mlotz.ch>
Distributed under the terms of the MIT license.
*/
* Copyright 2008-2009 Michael Lotz <mmlr@mlotz.ch>
* Distributed under the terms of the MIT license.
*/
#ifndef USB_MOUSE_DEVICE_H
#define USB_MOUSE_DEVICE_H
#include <InterfaceDefs.h>
#ifndef B_MAX_MOUSE_BUTTONS
#define B_MAX_MOUSE_BUTTONS 8
#endif
#include <InterfaceDefs.h>
#include "ProtocolHandler.h"
class HIDReportItem;
#ifndef B_MAX_MOUSE_BUTTONS
# define B_MAX_MOUSE_BUTTONS 8
#endif
class MouseDevice : public ProtocolHandler {
public:
MouseDevice(HIDReport *report,
HIDReportItem *xAxis, HIDReportItem *yAxis);
static ProtocolHandler * AddHandler(HIDDevice *device,
static ProtocolHandler * AddHandler(HIDDevice *device,
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:
status_t _ReadReport();
status_t _ReadReport();
HIDReport * fReport;
private:
HIDReport * fReport;
HIDReportItem * fXAxis;
HIDReportItem * fYAxis;
HIDReportItem * fWheel;
HIDReportItem * fButtons[B_MAX_MOUSE_BUTTONS];
HIDReportItem * fXAxis;
HIDReportItem * fYAxis;
HIDReportItem * fWheel;
HIDReportItem * fButtons[B_MAX_MOUSE_BUTTONS];
uint32 fLastButtons;
uint32 fClickCount;
bigtime_t fLastClickTime;
bigtime_t fClickSpeed;
uint32 fMaxButtons;
uint32 fLastButtons;
uint32 fClickCount;
bigtime_t fLastClickTime;
bigtime_t fClickSpeed;
uint32 fMaxButtons;
};
#endif // USB_MOUSE_DEVICE_H

View File

@ -3,6 +3,7 @@
* Distributed under the terms of the MIT License.
*/
#include <stdlib.h>
#include <ring_buffer.h>
@ -103,7 +104,7 @@ ProtocolHandler::AddHandlers(HIDDevice *device, ProtocolHandler ***handlerList,
status_t
ProtocolHandler::Open(uint32 flags)
ProtocolHandler::Open(uint32 flags, uint32 *cookie)
{
return fDevice->Open(this, flags);
}
@ -117,7 +118,7 @@ ProtocolHandler::Close()
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");
return B_ERROR;

View File

@ -5,48 +5,53 @@
#ifndef PROTOCOL_HANDLER_H
#define PROTOCOL_HANDLER_H
#include <SupportDefs.h>
class HIDDevice;
class HIDReport;
class ProtocolHandler {
public:
ProtocolHandler(HIDDevice *device,
const char *basePath,
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; };
void SetPublishPath(char *publishPath);
const char * PublishPath() { return fPublishPath; };
const char * BasePath() { return fBasePath; };
void SetPublishPath(char *publishPath);
const char * PublishPath() { return fPublishPath; };
static void AddHandlers(HIDDevice *device,
static void AddHandlers(HIDDevice *device,
ProtocolHandler ***handlerList,
uint32 *handlerCount);
virtual status_t Open(uint32 flags);
virtual status_t Close();
virtual status_t Open(uint32 flags, uint32 *cookie);
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();
status_t RingBufferRead(void *buffer, size_t length);
status_t RingBufferWrite(const void *buffer,
int32 RingBufferReadable();
status_t RingBufferRead(void *buffer, size_t length);
status_t RingBufferWrite(const void *buffer,
size_t length);
protected:
status_t fStatus;
status_t fStatus;
private:
HIDDevice * fDevice;
const char * fBasePath;
char * fPublishPath;
struct ring_buffer * fRingBuffer;
HIDDevice * fDevice;
const char * fBasePath;
char * fPublishPath;
struct ring_buffer *fRingBuffer;
};
#endif // PROTOCOL_HANDLER_H