* Cleanup and refactoring, made several Mouse-/Keyboard-/TouchpadDevice
functions private and moved them accordingly in the file. * I forgot to initialize the BObjectList to own the items in TouchpadInputDevice. * Changed the methods that read and apply settings in all three addons to be executed from the control threads only, which fixes race conditions. * The success of opening a device is no longer checked in the Start() method of the *Devices. Instead, the control thread checks the device before it enters the polling loop and cleans up if there was an error. This fixes non-running devices in the input_server because the PS/2 driver publishes devices which is has not checked yet for other reasons. It is important, however, to open() the devices in the Start() hook and not the control thread, otherwise there are unwanted race conditions in case node monitoring events are received more than once for the same device. That's the case for some reason on one of my computers for the AT 0 keyboard. TODO: * Combine the Touchpad and Mouse device addon into one, it's almost the same code except the Touchpad knows more settings and one more control message. * Refactor a common base class for Keyboard and Mouse device addon. * Fix the mouse speed/acceleration. If the speed is lowered from the default in the preflet, the mouse becomes almost unusable. To fix this, the same trick should be used as I used in the touchpad kernel driver, which is to sum up previous mouse moved fractional offsets. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28590 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
577fe1f9a1
commit
5125eae25d
@ -26,16 +26,60 @@
|
||||
#include "kb_mouse_driver.h"
|
||||
|
||||
|
||||
//#define TRACE_KEYBOARD_DEVICE
|
||||
#undef TRACE
|
||||
#define TRACE_KEYBOARD_DEVICE
|
||||
#ifdef TRACE_KEYBOARD_DEVICE
|
||||
# define LOG(text...) debug_printf(text)
|
||||
# define LOG_ERR(text...) LOG(text)
|
||||
#else
|
||||
# define LOG(text...) do {} while (0)
|
||||
# define LOG_ERR(text...) debug_printf(text)
|
||||
#endif
|
||||
|
||||
#define CALLED() LOG("%s\n", __PRETTY_FUNCTION__)
|
||||
class FunctionTracer {
|
||||
public:
|
||||
FunctionTracer(const void* pointer, const char* className,
|
||||
const char* functionName,
|
||||
int32& depth)
|
||||
: fFunctionName(),
|
||||
fPrepend(),
|
||||
fFunctionDepth(depth),
|
||||
fPointer(pointer)
|
||||
{
|
||||
fFunctionDepth++;
|
||||
fPrepend.Append(' ', fFunctionDepth * 2);
|
||||
fFunctionName << className << "::" << functionName << "()";
|
||||
|
||||
debug_printf("%p -> %s%s {\n", fPointer, fPrepend.String(),
|
||||
fFunctionName.String());
|
||||
}
|
||||
|
||||
~FunctionTracer()
|
||||
{
|
||||
debug_printf("%p -> %s}\n", fPointer, fPrepend.String());
|
||||
fFunctionDepth--;
|
||||
}
|
||||
|
||||
private:
|
||||
BString fFunctionName;
|
||||
BString fPrepend;
|
||||
int32& fFunctionDepth;
|
||||
const void* fPointer;
|
||||
};
|
||||
|
||||
|
||||
static int32 sFunctionDepth = -1;
|
||||
# define KD_CALLED(x...) FunctionTracer _ft(this, "KeyboardDevice", \
|
||||
__FUNCTION__, sFunctionDepth)
|
||||
# define KID_CALLED(x...) FunctionTracer _ft(this, "KeyboardInputDevice", \
|
||||
__FUNCTION__, sFunctionDepth)
|
||||
# define TRACE(x...) { BString _to; \
|
||||
_to.Append(' ', (sFunctionDepth + 1) * 2); \
|
||||
debug_printf("%p -> %s", this, _to.String()); \
|
||||
debug_printf(x); }
|
||||
# define LOG_EVENT(text...) do {} while (0)
|
||||
# define LOG_ERR(text...) TRACE(text)
|
||||
#else
|
||||
# define TRACE(x...) do {} while (0)
|
||||
# define KD_CALLED(x...) TRACE(x)
|
||||
# define KID_CALLED(x...) TRACE(x)
|
||||
# define LOG_ERR(text...) debug_printf(text)
|
||||
# define LOG_EVENT(text...) TRACE(x)
|
||||
#endif
|
||||
|
||||
|
||||
const static uint32 kKeyboardThreadPriority = B_FIRST_REAL_TIME_PRIORITY + 4;
|
||||
@ -346,7 +390,6 @@ instantiate_input_device()
|
||||
static char*
|
||||
get_short_name(const char* longName)
|
||||
{
|
||||
CALLED();
|
||||
BString string(longName);
|
||||
BString name;
|
||||
|
||||
@ -379,8 +422,12 @@ KeyboardDevice::KeyboardDevice(KeyboardInputDevice* owner, const char* path)
|
||||
fThread(-1),
|
||||
fActive(false),
|
||||
fInputMethodStarted(false),
|
||||
fUpdateSettings(false),
|
||||
fSettingsCommand(0),
|
||||
fKeymapLock("keymap lock")
|
||||
{
|
||||
KD_CALLED();
|
||||
|
||||
strcpy(fPath, path);
|
||||
fDeviceRef.name = get_short_name(path);
|
||||
fDeviceRef.type = B_KEYBOARD_DEVICE;
|
||||
@ -397,6 +444,9 @@ KeyboardDevice::KeyboardDevice(KeyboardInputDevice* owner, const char* path)
|
||||
|
||||
KeyboardDevice::~KeyboardDevice()
|
||||
{
|
||||
KD_CALLED();
|
||||
TRACE("delete\n");
|
||||
|
||||
if (fActive)
|
||||
Stop();
|
||||
|
||||
@ -409,37 +459,11 @@ KeyboardDevice::~KeyboardDevice()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
KeyboardDevice::EnqueueInlineInputMethod(int32 opcode,
|
||||
const char* string, bool confirmed, BMessage* keyDown)
|
||||
{
|
||||
BMessage* message = new BMessage(B_INPUT_METHOD_EVENT);
|
||||
if (message == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
message->AddInt32("be:opcode", opcode);
|
||||
message->AddBool("be:inline_only", true);
|
||||
|
||||
if (string != NULL)
|
||||
message->AddString("be:string", string);
|
||||
if (confirmed)
|
||||
message->AddBool("be:confirmed", true);
|
||||
if (keyDown)
|
||||
message->AddMessage("be:translated", keyDown);
|
||||
if (opcode == B_INPUT_METHOD_STARTED)
|
||||
message->AddMessenger("be:reply_to", this);
|
||||
|
||||
status_t status = fOwner->EnqueueMessage(message);
|
||||
if (status != B_OK)
|
||||
delete message;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
KeyboardDevice::MessageReceived(BMessage* message)
|
||||
{
|
||||
KD_CALLED();
|
||||
|
||||
if (message->what != B_INPUT_METHOD_EVENT) {
|
||||
BHandler::MessageReceived(message);
|
||||
return;
|
||||
@ -457,22 +481,21 @@ KeyboardDevice::MessageReceived(BMessage* message)
|
||||
status_t
|
||||
KeyboardDevice::Start()
|
||||
{
|
||||
if ((fFD = open(fPath, O_RDWR)) < B_OK) {
|
||||
fprintf(stderr, "error when opening %s: %s\n", fPath, strerror(errno));
|
||||
return B_ERROR;
|
||||
}
|
||||
KD_CALLED();
|
||||
TRACE("name: %s\n", fDeviceRef.name);
|
||||
|
||||
InitFromSettings();
|
||||
fFD = open(fPath, O_RDWR);
|
||||
// let the control thread handle any error on opening the device
|
||||
|
||||
char threadName[B_OS_NAME_LENGTH];
|
||||
snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", fDeviceRef.name);
|
||||
|
||||
fActive = true;
|
||||
fThread = spawn_thread(_ThreadEntry, threadName,
|
||||
fThread = spawn_thread(_ControlThreadEntry, threadName,
|
||||
kKeyboardThreadPriority, this);
|
||||
if (fThread < B_OK)
|
||||
return fThread;
|
||||
|
||||
fActive = true;
|
||||
resume_thread(fThread);
|
||||
return B_OK;
|
||||
}
|
||||
@ -480,6 +503,9 @@ KeyboardDevice::Start()
|
||||
void
|
||||
KeyboardDevice::Stop()
|
||||
{
|
||||
KD_CALLED();
|
||||
TRACE("name: %s\n", fDeviceRef.name);
|
||||
|
||||
fActive = false;
|
||||
|
||||
close(fFD);
|
||||
@ -495,70 +521,48 @@ KeyboardDevice::Stop()
|
||||
|
||||
|
||||
status_t
|
||||
KeyboardDevice::InitFromSettings(uint32 opcode)
|
||||
KeyboardDevice::UpdateSettings(uint32 opcode)
|
||||
{
|
||||
CALLED();
|
||||
KD_CALLED();
|
||||
|
||||
if (opcode == 0 || opcode == B_KEY_REPEAT_RATE_CHANGED) {
|
||||
if (get_key_repeat_rate(&fSettings.key_repeat_rate) != B_OK)
|
||||
LOG_ERR("error when get_key_repeat_rate\n");
|
||||
else if (ioctl(fFD, KB_SET_KEY_REPEAT_RATE,
|
||||
&fSettings.key_repeat_rate) != B_OK)
|
||||
LOG_ERR("error when KB_SET_KEY_REPEAT_RATE, fd:%d\n", fFD);
|
||||
}
|
||||
if (fThread < 0)
|
||||
return B_ERROR;
|
||||
|
||||
if (opcode == 0 || opcode == B_KEY_REPEAT_DELAY_CHANGED) {
|
||||
if (get_key_repeat_delay(&fSettings.key_repeat_delay) != B_OK)
|
||||
LOG_ERR("error when get_key_repeat_delay\n");
|
||||
else if (ioctl(fFD, KB_SET_KEY_REPEAT_DELAY,
|
||||
&fSettings.key_repeat_delay) != B_OK)
|
||||
LOG_ERR("error when KB_SET_KEY_REPEAT_DELAY, fd:%d\n", fFD);
|
||||
}
|
||||
|
||||
if (opcode == 0 || opcode == B_KEY_MAP_CHANGED
|
||||
|| opcode == B_KEY_LOCKS_CHANGED) {
|
||||
BAutolock lock(fKeymapLock);
|
||||
fKeymap.LoadCurrent();
|
||||
fModifiers = fKeymap.Locks();
|
||||
UpdateLEDs();
|
||||
}
|
||||
// schedule updating the settings from within the control thread
|
||||
fSettingsCommand = opcode;
|
||||
fUpdateSettings = true;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
KeyboardDevice::UpdateLEDs()
|
||||
{
|
||||
if (fFD < 0)
|
||||
return;
|
||||
|
||||
uint32 locks = fModifiers;
|
||||
char lockIO[3];
|
||||
memset(lockIO, 0, sizeof(lockIO));
|
||||
if (locks & B_NUM_LOCK)
|
||||
lockIO[0] = 1;
|
||||
if (locks & B_CAPS_LOCK)
|
||||
lockIO[1] = 1;
|
||||
if (locks & B_SCROLL_LOCK)
|
||||
lockIO[2] = 1;
|
||||
|
||||
ioctl(fFD, KB_SET_LEDS, &lockIO);
|
||||
}
|
||||
// #pragma mark - control thread
|
||||
|
||||
|
||||
/*static*/ int32
|
||||
KeyboardDevice::_ThreadEntry(void* arg)
|
||||
KeyboardDevice::_ControlThreadEntry(void* arg)
|
||||
{
|
||||
KeyboardDevice* device = (KeyboardDevice*)arg;
|
||||
return device->_Thread();
|
||||
return device->_ControlThread();
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
KeyboardDevice::_Thread()
|
||||
KeyboardDevice::_ControlThread()
|
||||
{
|
||||
CALLED();
|
||||
KD_CALLED();
|
||||
TRACE("fPath: %s\n", fPath);
|
||||
|
||||
if (fFD < B_OK) {
|
||||
LOG_ERR("KeyboardDevice: error when opening %s: %s\n",
|
||||
fPath, strerror(errno));
|
||||
_ControlThreadCleanup();
|
||||
// TOAST!
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
_UpdateSettings(0);
|
||||
|
||||
uint8 buffer[16];
|
||||
uint8 activeDeadKey = 0;
|
||||
uint32 lastKeyCode = 0;
|
||||
@ -568,29 +572,24 @@ KeyboardDevice::_Thread()
|
||||
|
||||
memset(states, 0, sizeof(states));
|
||||
|
||||
LOG("%s\n", __PRETTY_FUNCTION__);
|
||||
|
||||
while (fActive) {
|
||||
if (ioctl(fFD, KB_READ, &buffer) != B_OK) {
|
||||
if (fActive) {
|
||||
fThread = -1;
|
||||
fOwner->_RemoveDevice(fPath);
|
||||
} else {
|
||||
// In case fActive is already false, another thread
|
||||
// waits for this thread to quit, and may already hold
|
||||
// locks that _RemoveDevice() wants to acquire. In another
|
||||
// words, the device is already being removed, so we simply
|
||||
// quit here.
|
||||
}
|
||||
_ControlThreadCleanup();
|
||||
// TOAST!
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Update the settings from this thread if necessary
|
||||
if (fUpdateSettings) {
|
||||
_UpdateSettings(fSettingsCommand);
|
||||
fUpdateSettings = false;
|
||||
}
|
||||
|
||||
uint32 keycode = 0;
|
||||
bool isKeyDown = false;
|
||||
bigtime_t timestamp = 0;
|
||||
|
||||
LOG("KB_READ :");
|
||||
LOG_EVENT("KB_READ :");
|
||||
|
||||
if (fIsAT) {
|
||||
at_kbd_io* atKeyboard = (at_kbd_io*)buffer;
|
||||
@ -598,7 +597,7 @@ KeyboardDevice::_Thread()
|
||||
keycode = kATKeycodeMap[atKeyboard->scancode - 1];
|
||||
isKeyDown = atKeyboard->is_keydown;
|
||||
timestamp = atKeyboard->timestamp;
|
||||
LOG(" %02x", atKeyboard->scancode);
|
||||
LOG_EVENT(" %02x", atKeyboard->scancode);
|
||||
} else {
|
||||
raw_key_info* rawKeyInfo= (raw_key_info*)buffer;
|
||||
isKeyDown = rawKeyInfo->is_keydown;
|
||||
@ -609,7 +608,7 @@ KeyboardDevice::_Thread()
|
||||
if (keycode == 0)
|
||||
continue;
|
||||
|
||||
LOG(" %Ld, %02x, %02lx\n", timestamp, isKeyDown, keycode);
|
||||
LOG_EVENT(" %Ld, %02x, %02lx\n", timestamp, isKeyDown, keycode);
|
||||
|
||||
if (isKeyDown && keycode == 0x68) {
|
||||
// MENU KEY for Tracker
|
||||
@ -638,7 +637,7 @@ KeyboardDevice::_Thread()
|
||||
if (isKeyDown && keycode == 0x34 // DELETE KEY
|
||||
&& (states[0x5c >> 3] & (1 << (7 - (0x5c & 0x7))))
|
||||
&& (states[0x5d >> 3] & (1 << (7 - (0x5d & 0x7))))) {
|
||||
LOG("TeamMonitor called\n");
|
||||
LOG_EVENT("TeamMonitor called\n");
|
||||
|
||||
// show the team monitor
|
||||
if (fOwner->fTeamMonitorWindow == NULL)
|
||||
@ -686,7 +685,7 @@ KeyboardDevice::_Thread()
|
||||
delete msg;
|
||||
|
||||
if (modifiers & (B_CAPS_LOCK | B_NUM_LOCK | B_SCROLL_LOCK))
|
||||
UpdateLEDs();
|
||||
_UpdateLEDs();
|
||||
}
|
||||
|
||||
uint8 newDeadKey = 0;
|
||||
@ -745,25 +744,25 @@ KeyboardDevice::_Thread()
|
||||
if (isKeyDown && !modifiers && activeDeadKey != 0
|
||||
&& fInputMethodStarted) {
|
||||
// a dead key was completed
|
||||
EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED,
|
||||
_EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED,
|
||||
string, true, msg);
|
||||
} else if (fOwner->EnqueueMessage(msg) != B_OK)
|
||||
delete msg;
|
||||
} else if (isKeyDown) {
|
||||
// start of a dead key
|
||||
if (EnqueueInlineInputMethod(B_INPUT_METHOD_STARTED) == B_OK) {
|
||||
if (_EnqueueInlineInputMethod(B_INPUT_METHOD_STARTED) == B_OK) {
|
||||
char* string = NULL;
|
||||
int32 numBytes = 0;
|
||||
fKeymap.GetChars(keycode, fModifiers, 0, &string, &numBytes);
|
||||
|
||||
if (EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, string) == B_OK)
|
||||
if (_EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, string) == B_OK)
|
||||
fInputMethodStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isKeyDown && !modifiers) {
|
||||
if (activeDeadKey != 0) {
|
||||
EnqueueInlineInputMethod(B_INPUT_METHOD_STOPPED);
|
||||
_EnqueueInlineInputMethod(B_INPUT_METHOD_STOPPED);
|
||||
fInputMethodStarted = false;
|
||||
}
|
||||
|
||||
@ -777,15 +776,116 @@ KeyboardDevice::_Thread()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
KeyboardDevice::_ControlThreadCleanup()
|
||||
{
|
||||
// NOTE: Only executed when the control thread detected an error
|
||||
// and from within the control thread!
|
||||
|
||||
if (fActive) {
|
||||
fThread = -1;
|
||||
fOwner->_RemoveDevice(fPath);
|
||||
} else {
|
||||
// In case active is already false, another thread
|
||||
// waits for this thread to quit, and may already hold
|
||||
// locks that _RemoveDevice() wants to acquire. In another
|
||||
// words, the device is already being removed, so we simply
|
||||
// quit here.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
KeyboardDevice::_UpdateSettings(uint32 opcode)
|
||||
{
|
||||
KD_CALLED();
|
||||
|
||||
if (opcode == 0 || opcode == B_KEY_REPEAT_RATE_CHANGED) {
|
||||
if (get_key_repeat_rate(&fSettings.key_repeat_rate) != B_OK) {
|
||||
LOG_ERR("error when get_key_repeat_rate\n");
|
||||
} else if (ioctl(fFD, KB_SET_KEY_REPEAT_RATE,
|
||||
&fSettings.key_repeat_rate) != B_OK) {
|
||||
LOG_ERR("error when KB_SET_KEY_REPEAT_RATE, fd:%d\n", fFD);
|
||||
}
|
||||
}
|
||||
|
||||
if (opcode == 0 || opcode == B_KEY_REPEAT_DELAY_CHANGED) {
|
||||
if (get_key_repeat_delay(&fSettings.key_repeat_delay) != B_OK) {
|
||||
LOG_ERR("error when get_key_repeat_delay\n");
|
||||
} else if (ioctl(fFD, KB_SET_KEY_REPEAT_DELAY,
|
||||
&fSettings.key_repeat_delay) != B_OK) {
|
||||
LOG_ERR("error when KB_SET_KEY_REPEAT_DELAY, fd:%d\n", fFD);
|
||||
}
|
||||
}
|
||||
|
||||
if (opcode == 0 || opcode == B_KEY_MAP_CHANGED
|
||||
|| opcode == B_KEY_LOCKS_CHANGED) {
|
||||
BAutolock lock(fKeymapLock);
|
||||
fKeymap.LoadCurrent();
|
||||
fModifiers = fKeymap.Locks();
|
||||
_UpdateLEDs();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
KeyboardDevice::_UpdateLEDs()
|
||||
{
|
||||
if (fFD < 0)
|
||||
return;
|
||||
|
||||
uint32 locks = fModifiers;
|
||||
char lockIO[3];
|
||||
memset(lockIO, 0, sizeof(lockIO));
|
||||
if (locks & B_NUM_LOCK)
|
||||
lockIO[0] = 1;
|
||||
if (locks & B_CAPS_LOCK)
|
||||
lockIO[1] = 1;
|
||||
if (locks & B_SCROLL_LOCK)
|
||||
lockIO[2] = 1;
|
||||
|
||||
ioctl(fFD, KB_SET_LEDS, &lockIO);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
KeyboardDevice::_EnqueueInlineInputMethod(int32 opcode,
|
||||
const char* string, bool confirmed, BMessage* keyDown)
|
||||
{
|
||||
BMessage* message = new BMessage(B_INPUT_METHOD_EVENT);
|
||||
if (message == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
message->AddInt32("be:opcode", opcode);
|
||||
message->AddBool("be:inline_only", true);
|
||||
|
||||
if (string != NULL)
|
||||
message->AddString("be:string", string);
|
||||
if (confirmed)
|
||||
message->AddBool("be:confirmed", true);
|
||||
if (keyDown)
|
||||
message->AddMessage("be:translated", keyDown);
|
||||
if (opcode == B_INPUT_METHOD_STARTED)
|
||||
message->AddMessenger("be:reply_to", this);
|
||||
|
||||
status_t status = fOwner->EnqueueMessage(message);
|
||||
if (status != B_OK)
|
||||
delete message;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
KeyboardInputDevice::KeyboardInputDevice()
|
||||
:
|
||||
fDevices(2, true),
|
||||
fDeviceListLock("KeyboardInputDevice list"),
|
||||
fTeamMonitorWindow(NULL)
|
||||
{
|
||||
CALLED();
|
||||
KID_CALLED();
|
||||
|
||||
StartMonitoringDevice(kKeyboardDevicesDirectory);
|
||||
_RecursiveScan(kKeyboardDevicesDirectory);
|
||||
@ -794,7 +894,7 @@ KeyboardInputDevice::KeyboardInputDevice()
|
||||
|
||||
KeyboardInputDevice::~KeyboardInputDevice()
|
||||
{
|
||||
CALLED();
|
||||
KID_CALLED();
|
||||
|
||||
if (fTeamMonitorWindow) {
|
||||
fTeamMonitorWindow->PostMessage(B_QUIT_REQUESTED);
|
||||
@ -809,7 +909,7 @@ KeyboardInputDevice::~KeyboardInputDevice()
|
||||
status_t
|
||||
KeyboardInputDevice::SystemShuttingDown()
|
||||
{
|
||||
CALLED();
|
||||
KID_CALLED();
|
||||
if (fTeamMonitorWindow)
|
||||
fTeamMonitorWindow->PostMessage(SYSTEM_SHUTTING_DOWN);
|
||||
|
||||
@ -820,7 +920,7 @@ KeyboardInputDevice::SystemShuttingDown()
|
||||
status_t
|
||||
KeyboardInputDevice::InitCheck()
|
||||
{
|
||||
CALLED();
|
||||
KID_CALLED();
|
||||
return BInputServerDevice::InitCheck();
|
||||
}
|
||||
|
||||
@ -828,7 +928,9 @@ KeyboardInputDevice::InitCheck()
|
||||
status_t
|
||||
KeyboardInputDevice::Start(const char* name, void* cookie)
|
||||
{
|
||||
CALLED();
|
||||
KID_CALLED();
|
||||
TRACE("name %s\n", name);
|
||||
|
||||
KeyboardDevice* device = (KeyboardDevice*)cookie;
|
||||
|
||||
return device->Start();
|
||||
@ -838,10 +940,10 @@ KeyboardInputDevice::Start(const char* name, void* cookie)
|
||||
status_t
|
||||
KeyboardInputDevice::Stop(const char* name, void* cookie)
|
||||
{
|
||||
CALLED();
|
||||
KeyboardDevice* device = (KeyboardDevice*)cookie;
|
||||
KID_CALLED();
|
||||
TRACE("name %s\n", name);
|
||||
|
||||
LOG("Stop(%s)\n", name);
|
||||
KeyboardDevice* device = (KeyboardDevice*)cookie;
|
||||
|
||||
device->Stop();
|
||||
return B_OK;
|
||||
@ -852,15 +954,15 @@ status_t
|
||||
KeyboardInputDevice::Control(const char* name, void* cookie,
|
||||
uint32 command, BMessage* message)
|
||||
{
|
||||
CALLED();
|
||||
LOG("Control(%s, code: %lu)\n", name, command);
|
||||
KID_CALLED();
|
||||
TRACE("KeyboardInputDevice::Control(%s, code: %lu)\n", name, command);
|
||||
|
||||
if (command == B_NODE_MONITOR)
|
||||
_HandleMonitor(message);
|
||||
else if (command >= B_KEY_MAP_CHANGED
|
||||
&& command <= B_KEY_REPEAT_RATE_CHANGED) {
|
||||
KeyboardDevice* device = (KeyboardDevice*)cookie;
|
||||
device->InitFromSettings(command);
|
||||
device->UpdateSettings(command);
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
@ -869,7 +971,7 @@ KeyboardInputDevice::Control(const char* name, void* cookie,
|
||||
status_t
|
||||
KeyboardInputDevice::_HandleMonitor(BMessage* message)
|
||||
{
|
||||
CALLED();
|
||||
KID_CALLED();
|
||||
|
||||
const char* path;
|
||||
int32 opcode;
|
||||
@ -906,7 +1008,10 @@ KeyboardInputDevice::_FindDevice(const char* path) const
|
||||
status_t
|
||||
KeyboardInputDevice::_AddDevice(const char* path)
|
||||
{
|
||||
CALLED();
|
||||
KID_CALLED();
|
||||
TRACE("path: %s\n", path);
|
||||
|
||||
BAutolock _(fDeviceListLock);
|
||||
|
||||
_RemoveDevice(path);
|
||||
|
||||
@ -927,12 +1032,15 @@ KeyboardInputDevice::_AddDevice(const char* path)
|
||||
status_t
|
||||
KeyboardInputDevice::_RemoveDevice(const char* path)
|
||||
{
|
||||
CALLED();
|
||||
BAutolock _(fDeviceListLock);
|
||||
|
||||
KeyboardDevice* device = _FindDevice(path);
|
||||
if (device == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
KID_CALLED();
|
||||
TRACE("path: %s\n", path);
|
||||
|
||||
input_device_ref* devices[2];
|
||||
devices[0] = device->DeviceRef();
|
||||
devices[1] = NULL;
|
||||
@ -948,7 +1056,9 @@ KeyboardInputDevice::_RemoveDevice(const char* path)
|
||||
void
|
||||
KeyboardInputDevice::_RecursiveScan(const char* directory)
|
||||
{
|
||||
CALLED();
|
||||
KID_CALLED();
|
||||
TRACE("directory: %s\n", directory);
|
||||
|
||||
BEntry entry;
|
||||
BDirectory dir(directory);
|
||||
while (dir.GetNextEntry(&entry) == B_OK) {
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include <Handler.h>
|
||||
#include <InputServerDevice.h>
|
||||
#include <Locker.h>
|
||||
#include <List.h>
|
||||
|
||||
#include <InputServerTypes.h>
|
||||
#include <ObjectList.h>
|
||||
@ -29,23 +28,24 @@ public:
|
||||
virtual ~KeyboardDevice();
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
status_t EnqueueInlineInputMethod(int32 opcode,
|
||||
const char* string = NULL,
|
||||
bool confirmed = false,
|
||||
BMessage* keyDown = NULL);
|
||||
|
||||
status_t Start();
|
||||
void Stop();
|
||||
|
||||
status_t InitFromSettings(uint32 opcode = 0);
|
||||
void UpdateLEDs();
|
||||
status_t UpdateSettings(uint32 opcode = 0);
|
||||
|
||||
const char* Path() const { return fPath; }
|
||||
input_device_ref* DeviceRef() { return &fDeviceRef; }
|
||||
|
||||
private:
|
||||
static int32 _ThreadEntry(void* arg);
|
||||
int32 _Thread();
|
||||
static int32 _ControlThreadEntry(void* arg);
|
||||
int32 _ControlThread();
|
||||
void _ControlThreadCleanup();
|
||||
void _UpdateSettings(uint32 opcode);
|
||||
void _UpdateLEDs();
|
||||
status_t _EnqueueInlineInputMethod(int32 opcode,
|
||||
const char* string = NULL,
|
||||
bool confirmed = false,
|
||||
BMessage* keyDown = NULL);
|
||||
|
||||
private:
|
||||
KeyboardInputDevice* fOwner;
|
||||
@ -59,6 +59,9 @@ private:
|
||||
volatile bool fInputMethodStarted;
|
||||
uint32 fModifiers;
|
||||
|
||||
volatile bool fUpdateSettings;
|
||||
volatile uint32 fSettingsCommand;
|
||||
|
||||
Keymap fKeymap;
|
||||
BLocker fKeymapLock;
|
||||
};
|
||||
@ -92,6 +95,7 @@ private:
|
||||
status_t _RemoveDevice(const char* path);
|
||||
|
||||
BObjectList<KeyboardDevice> fDevices;
|
||||
BLocker fDeviceListLock;
|
||||
TeamMonitorWindow* fTeamMonitorWindow;
|
||||
};
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <Debug.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
@ -31,7 +32,6 @@
|
||||
|
||||
|
||||
#undef TRACE
|
||||
#undef CALLED
|
||||
//#define TRACE_MOUSE_DEVICE
|
||||
#ifdef TRACE_MOUSE_DEVICE
|
||||
|
||||
@ -76,64 +76,63 @@
|
||||
_to.Append(' ', (sFunctionDepth + 1) * 2); \
|
||||
debug_printf("%p -> %s", this, _to.String()); \
|
||||
debug_printf(x); }
|
||||
# define LOG(text...) debug_printf(text)
|
||||
# define LOG_EVENT(text...) do {} while (0)
|
||||
# define LOG_ERR(text...) LOG(text)
|
||||
# define LOG_ERR(text...) TRACE(text)
|
||||
#else
|
||||
# define TRACE(x...) do {} while (0)
|
||||
# define MD_CALLED(x...) TRACE(x)
|
||||
# define MID_CALLED(x...) TRACE(x)
|
||||
# define LOG(text...) TRACE(x)
|
||||
# define LOG_ERR(text...) debug_printf(text)
|
||||
# define LOG_EVENT(text...) TRACE(x)
|
||||
#endif
|
||||
|
||||
|
||||
//#define LOG_DEVICES(text...) debug_printf(text)
|
||||
#define LOG_DEVICES(text...) LOG(text)
|
||||
|
||||
|
||||
|
||||
const static uint32 kMouseThreadPriority = B_FIRST_REAL_TIME_PRIORITY + 4;
|
||||
const static char* kMouseDevicesDirectory = "/dev/input/mouse";
|
||||
|
||||
|
||||
class MouseDevice {
|
||||
public:
|
||||
MouseDevice(MouseInputDevice& target, const char* path);
|
||||
~MouseDevice();
|
||||
public:
|
||||
MouseDevice(MouseInputDevice& target,
|
||||
const char* path);
|
||||
~MouseDevice();
|
||||
|
||||
status_t Start();
|
||||
void Stop();
|
||||
status_t Start();
|
||||
void Stop();
|
||||
|
||||
status_t UpdateSettings();
|
||||
status_t UpdateSettings();
|
||||
|
||||
const char* Path() const { return fPath.String(); }
|
||||
input_device_ref* DeviceRef() { return &fDeviceRef; }
|
||||
const char* Path() const { return fPath.String(); }
|
||||
input_device_ref* DeviceRef() { return &fDeviceRef; }
|
||||
|
||||
private:
|
||||
void _Run();
|
||||
static status_t _ThreadFunction(void* arg);
|
||||
private:
|
||||
char* _BuildShortName() const;
|
||||
|
||||
BMessage* _BuildMouseMessage(uint32 what, uint64 when, uint32 buttons,
|
||||
int32 deltaX, int32 deltaY) const;
|
||||
void _ComputeAcceleration(const mouse_movement& movements,
|
||||
int32& deltaX, int32& deltaY) const;
|
||||
uint32 _RemapButtons(uint32 buttons) const;
|
||||
static status_t _ControlThreadEntry(void* arg);
|
||||
void _ControlThread();
|
||||
void _ControlThreadCleanup();
|
||||
void _UpdateSettings();
|
||||
|
||||
char* _BuildShortName() const;
|
||||
BMessage* _BuildMouseMessage(uint32 what,
|
||||
uint64 when, uint32 buttons,
|
||||
int32 deltaX, int32 deltaY) const;
|
||||
void _ComputeAcceleration(
|
||||
const mouse_movement& movements,
|
||||
int32& deltaX, int32& deltaY) const;
|
||||
uint32 _RemapButtons(uint32 buttons) const;
|
||||
|
||||
private:
|
||||
MouseInputDevice& fTarget;
|
||||
BString fPath;
|
||||
int fDevice;
|
||||
private:
|
||||
MouseInputDevice& fTarget;
|
||||
BString fPath;
|
||||
int fDevice;
|
||||
|
||||
input_device_ref fDeviceRef;
|
||||
mouse_settings fSettings;
|
||||
bool fDeviceRemapsButtons;
|
||||
input_device_ref fDeviceRef;
|
||||
mouse_settings fSettings;
|
||||
bool fDeviceRemapsButtons;
|
||||
|
||||
thread_id fThread;
|
||||
volatile bool fActive;
|
||||
thread_id fThread;
|
||||
volatile bool fActive;
|
||||
volatile bool fUpdateSettings;
|
||||
};
|
||||
|
||||
|
||||
@ -154,7 +153,8 @@ MouseDevice::MouseDevice(MouseInputDevice& target, const char* driverPath)
|
||||
fDevice(-1),
|
||||
fDeviceRemapsButtons(false),
|
||||
fThread(-1),
|
||||
fActive(false)
|
||||
fActive(false),
|
||||
fUpdateSettings(false)
|
||||
{
|
||||
MD_CALLED();
|
||||
|
||||
@ -175,9 +175,6 @@ MouseDevice::~MouseDevice()
|
||||
MD_CALLED();
|
||||
TRACE("delete\n");
|
||||
|
||||
if (fTarget._HasDevice(this))
|
||||
TRACE("still in the list!\n");
|
||||
|
||||
if (fActive)
|
||||
Stop();
|
||||
|
||||
@ -191,15 +188,12 @@ MouseDevice::Start()
|
||||
MD_CALLED();
|
||||
|
||||
fDevice = open(fPath.String(), O_RDWR);
|
||||
if (fDevice < 0)
|
||||
return errno;
|
||||
|
||||
UpdateSettings();
|
||||
// let the control thread handle any error on opening the device
|
||||
|
||||
char threadName[B_OS_NAME_LENGTH];
|
||||
snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", fDeviceRef.name);
|
||||
|
||||
fThread = spawn_thread(_ThreadFunction, threadName,
|
||||
fThread = spawn_thread(_ControlThreadEntry, threadName,
|
||||
kMouseThreadPriority, (void*)this);
|
||||
|
||||
status_t status;
|
||||
@ -213,7 +207,6 @@ MouseDevice::Start()
|
||||
if (status < B_OK) {
|
||||
LOG_ERR("%s: can't spawn/resume watching thread: %s\n",
|
||||
fDeviceRef.name, strerror(status));
|
||||
close(fDevice);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -248,45 +241,63 @@ MouseDevice::UpdateSettings()
|
||||
{
|
||||
MD_CALLED();
|
||||
|
||||
// retrieve current values
|
||||
if (fThread < 0)
|
||||
return B_ERROR;
|
||||
|
||||
if (get_mouse_map(&fSettings.map) != B_OK)
|
||||
LOG_ERR("error when get_mouse_map\n");
|
||||
else
|
||||
fDeviceRemapsButtons = ioctl(fDevice, MS_SET_MAP, &fSettings.map) == B_OK;
|
||||
|
||||
if (get_click_speed(&fSettings.click_speed) != B_OK)
|
||||
LOG_ERR("error when get_click_speed\n");
|
||||
else
|
||||
ioctl(fDevice, MS_SET_CLICKSPEED, &fSettings.click_speed);
|
||||
|
||||
if (get_mouse_speed(&fSettings.accel.speed) != B_OK)
|
||||
LOG_ERR("error when get_mouse_speed\n");
|
||||
else {
|
||||
if (get_mouse_acceleration(&fSettings.accel.accel_factor) != B_OK)
|
||||
LOG_ERR("error when get_mouse_acceleration\n");
|
||||
else {
|
||||
mouse_accel accel;
|
||||
ioctl(fDevice, MS_GET_ACCEL, &accel);
|
||||
accel.speed = fSettings.accel.speed;
|
||||
accel.accel_factor = fSettings.accel.accel_factor;
|
||||
ioctl(fDevice, MS_SET_ACCEL, &fSettings.accel);
|
||||
}
|
||||
}
|
||||
|
||||
if (get_mouse_type(&fSettings.type) != B_OK)
|
||||
LOG_ERR("error when get_mouse_type\n");
|
||||
else
|
||||
ioctl(fDevice, MS_SET_TYPE, &fSettings.type);
|
||||
fUpdateSettings = true;
|
||||
// This will provoke the control thread to update the settings.
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
MouseDevice::_BuildShortName() const
|
||||
{
|
||||
BString string(fPath);
|
||||
BString name;
|
||||
|
||||
int32 slash = string.FindLast("/");
|
||||
string.CopyInto(name, slash + 1, string.Length() - slash);
|
||||
int32 index = atoi(name.String()) + 1;
|
||||
|
||||
int32 previousSlash = string.FindLast("/", slash);
|
||||
string.CopyInto(name, previousSlash + 1, slash - previousSlash - 1);
|
||||
|
||||
if (name == "ps2")
|
||||
name = "PS/2";
|
||||
else
|
||||
name.Capitalize();
|
||||
|
||||
name << " Mouse " << index;
|
||||
|
||||
return strdup(name.String());
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - control thread
|
||||
|
||||
|
||||
status_t
|
||||
MouseDevice::_ControlThreadEntry(void* arg)
|
||||
{
|
||||
MouseDevice* device = (MouseDevice*)arg;
|
||||
device->_ControlThread();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MouseDevice::_Run()
|
||||
MouseDevice::_ControlThread()
|
||||
{
|
||||
if (fDevice < 0) {
|
||||
_ControlThreadCleanup();
|
||||
// TOAST!
|
||||
return;
|
||||
}
|
||||
|
||||
_UpdateSettings();
|
||||
|
||||
uint32 lastButtons = 0;
|
||||
|
||||
while (fActive) {
|
||||
@ -294,20 +305,17 @@ MouseDevice::_Run()
|
||||
memset(&movements, 0, sizeof(movements));
|
||||
|
||||
if (ioctl(fDevice, MS_READ, &movements) != B_OK) {
|
||||
if (fActive) {
|
||||
fThread = -1;
|
||||
fTarget._RemoveDevice(fPath.String());
|
||||
} else {
|
||||
// In case active is already false, another thread
|
||||
// waits for this thread to quit, and may already hold
|
||||
// locks that _RemoveDevice() wants to acquire. In another
|
||||
// words, the device is already being removed, so we simply
|
||||
// quit here.
|
||||
}
|
||||
_ControlThreadCleanup();
|
||||
// TOAST!
|
||||
return;
|
||||
}
|
||||
|
||||
// take care of updating the settings first, if necessary
|
||||
if (fUpdateSettings) {
|
||||
_UpdateSettings();
|
||||
fUpdateSettings = false;
|
||||
}
|
||||
|
||||
uint32 buttons = lastButtons ^ movements.buttons;
|
||||
|
||||
uint32 remappedButtons = _RemapButtons(movements.buttons);
|
||||
@ -361,12 +369,62 @@ MouseDevice::_Run()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
MouseDevice::_ThreadFunction(void* arg)
|
||||
void
|
||||
MouseDevice::_ControlThreadCleanup()
|
||||
{
|
||||
MouseDevice* device = (MouseDevice*)arg;
|
||||
device->_Run();
|
||||
return B_OK;
|
||||
// NOTE: Only executed when the control thread detected an error
|
||||
// and from within the control thread!
|
||||
|
||||
if (fActive) {
|
||||
fThread = -1;
|
||||
fTarget._RemoveDevice(fPath.String());
|
||||
} else {
|
||||
// In case active is already false, another thread
|
||||
// waits for this thread to quit, and may already hold
|
||||
// locks that _RemoveDevice() wants to acquire. In another
|
||||
// words, the device is already being removed, so we simply
|
||||
// quit here.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MouseDevice::_UpdateSettings()
|
||||
{
|
||||
MD_CALLED();
|
||||
|
||||
// retrieve current values
|
||||
|
||||
if (get_mouse_map(&fSettings.map) != B_OK)
|
||||
LOG_ERR("error when get_mouse_map\n");
|
||||
else {
|
||||
fDeviceRemapsButtons
|
||||
= ioctl(fDevice, MS_SET_MAP, &fSettings.map) == B_OK;
|
||||
}
|
||||
|
||||
if (get_click_speed(&fSettings.click_speed) != B_OK)
|
||||
LOG_ERR("error when get_click_speed\n");
|
||||
else
|
||||
ioctl(fDevice, MS_SET_CLICKSPEED, &fSettings.click_speed);
|
||||
|
||||
if (get_mouse_speed(&fSettings.accel.speed) != B_OK)
|
||||
LOG_ERR("error when get_mouse_speed\n");
|
||||
else {
|
||||
if (get_mouse_acceleration(&fSettings.accel.accel_factor) != B_OK)
|
||||
LOG_ERR("error when get_mouse_acceleration\n");
|
||||
else {
|
||||
mouse_accel accel;
|
||||
ioctl(fDevice, MS_GET_ACCEL, &accel);
|
||||
accel.speed = fSettings.accel.speed;
|
||||
accel.accel_factor = fSettings.accel.accel_factor;
|
||||
ioctl(fDevice, MS_SET_ACCEL, &fSettings.accel);
|
||||
}
|
||||
}
|
||||
|
||||
if (get_mouse_type(&fSettings.type) != B_OK)
|
||||
LOG_ERR("error when get_mouse_type\n");
|
||||
else
|
||||
ioctl(fDevice, MS_SET_TYPE, &fSettings.type);
|
||||
}
|
||||
|
||||
|
||||
@ -445,36 +503,13 @@ MouseDevice::_RemapButtons(uint32 buttons) const
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
MouseDevice::_BuildShortName() const
|
||||
{
|
||||
BString string(fPath);
|
||||
BString name;
|
||||
|
||||
int32 slash = string.FindLast("/");
|
||||
string.CopyInto(name, slash + 1, string.Length() - slash);
|
||||
int32 index = atoi(name.String()) + 1;
|
||||
|
||||
int32 previousSlash = string.FindLast("/", slash);
|
||||
string.CopyInto(name, previousSlash + 1, slash - previousSlash - 1);
|
||||
|
||||
if (name == "ps2")
|
||||
name = "PS/2";
|
||||
else
|
||||
name.Capitalize();
|
||||
|
||||
name << " Mouse " << index;
|
||||
|
||||
return strdup(name.String());
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
MouseInputDevice::MouseInputDevice()
|
||||
:
|
||||
fDevices(2, true)
|
||||
fDevices(2, true),
|
||||
fDeviceListLock("MouseInputDevice list")
|
||||
{
|
||||
MID_CALLED();
|
||||
|
||||
@ -592,7 +627,7 @@ MouseInputDevice::_RecursiveScan(const char* directory)
|
||||
|
||||
|
||||
MouseDevice*
|
||||
MouseInputDevice::_FindDevice(const char* path)
|
||||
MouseInputDevice::_FindDevice(const char* path) const
|
||||
{
|
||||
MID_CALLED();
|
||||
|
||||
@ -611,6 +646,8 @@ MouseInputDevice::_AddDevice(const char* path)
|
||||
{
|
||||
MID_CALLED();
|
||||
|
||||
BAutolock _(fDeviceListLock);
|
||||
|
||||
_RemoveDevice(path);
|
||||
|
||||
MouseDevice* device = new(std::nothrow) MouseDevice(*this, path);
|
||||
@ -640,6 +677,8 @@ MouseInputDevice::_RemoveDevice(const char* path)
|
||||
{
|
||||
MID_CALLED();
|
||||
|
||||
BAutolock _(fDeviceListLock);
|
||||
|
||||
MouseDevice* device = _FindDevice(path);
|
||||
if (device == NULL) {
|
||||
TRACE("%s not found\n", path);
|
||||
@ -660,14 +699,4 @@ MouseInputDevice::_RemoveDevice(const char* path)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
MouseInputDevice::_HasDevice(const MouseDevice* device) const
|
||||
{
|
||||
for (int32 i = fDevices.CountItems() - 1; i >= 0; i--) {
|
||||
if (device == fDevices.ItemAt(i))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <InputServerDevice.h>
|
||||
#include <InterfaceDefs.h>
|
||||
#include <Locker.h>
|
||||
|
||||
#include <ObjectList.h>
|
||||
|
||||
@ -38,14 +39,13 @@ private:
|
||||
status_t _HandleMonitor(BMessage* message);
|
||||
void _RecursiveScan(const char* directory);
|
||||
|
||||
MouseDevice* _FindDevice(const char* path);
|
||||
MouseDevice* _FindDevice(const char* path) const;
|
||||
status_t _AddDevice(const char* path);
|
||||
status_t _RemoveDevice(const char* path);
|
||||
|
||||
bool _HasDevice(const MouseDevice* device) const;
|
||||
|
||||
private:
|
||||
BObjectList<MouseDevice> fDevices;
|
||||
BLocker fDeviceListLock;
|
||||
};
|
||||
|
||||
extern "C" BInputServerDevice* instantiate_input_device();
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "kb_mouse_settings.h"
|
||||
#include "touchpad_settings.h"
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <Debug.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
@ -49,50 +50,57 @@ const static char* kTouchpadDevicesDirectoryPS2 = "/dev/input/touchpad/ps2";
|
||||
|
||||
|
||||
class TouchpadDevice {
|
||||
public:
|
||||
TouchpadDevice(TouchpadInputDevice& target, const char* path);
|
||||
~TouchpadDevice();
|
||||
public:
|
||||
TouchpadDevice(TouchpadInputDevice& target,
|
||||
const char* path);
|
||||
~TouchpadDevice();
|
||||
|
||||
status_t Start();
|
||||
void Stop();
|
||||
status_t Start();
|
||||
void Stop();
|
||||
|
||||
status_t UpdateSettings();
|
||||
status_t UpdateSettings();
|
||||
status_t UpdateTouchpadSettings(const BMessage* message);
|
||||
|
||||
const char* Path() const { return fPath.String(); }
|
||||
input_device_ref* DeviceRef() { return &fDeviceRef; }
|
||||
const char* Path() const { return fPath.String(); }
|
||||
input_device_ref* DeviceRef() { return &fDeviceRef; }
|
||||
|
||||
bool IsTouchpad() { return fIsTouchpad; }
|
||||
status_t ReadTouchpadSettingsMsg(BMessage* msg);
|
||||
status_t UpdateTouchpadSettings();
|
||||
private:
|
||||
char* _BuildShortName() const;
|
||||
|
||||
private:
|
||||
void _Run();
|
||||
static status_t _ThreadFunction(void *arg);
|
||||
static status_t _ControlThreadEntry(void *arg);
|
||||
void _ControlThread();
|
||||
void _ControlThreadCleanup();
|
||||
void _UpdateSettings();
|
||||
|
||||
BMessage* _BuildMouseMessage(uint32 what, uint64 when, uint32 buttons,
|
||||
int32 deltaX, int32 deltaY) const;
|
||||
void _ComputeAcceleration(const mouse_movement& movements,
|
||||
int32& deltaX, int32& deltaY) const;
|
||||
uint32 _RemapButtons(uint32 buttons) const;
|
||||
status_t _GetSettingsPath(BPath &path);
|
||||
status_t _ReadTouchpadSettingsMsg(BMessage* message);
|
||||
status_t _UpdateTouchpadSettings();
|
||||
|
||||
char* _BuildShortName() const;
|
||||
BMessage* _BuildMouseMessage(uint32 what,
|
||||
uint64 when, uint32 buttons,
|
||||
int32 deltaX, int32 deltaY) const;
|
||||
void _ComputeAcceleration(
|
||||
const mouse_movement& movements,
|
||||
int32& deltaX, int32& deltaY) const;
|
||||
uint32 _RemapButtons(uint32 buttons) const;
|
||||
|
||||
status_t _GetSettingsPath(BPath &path);
|
||||
private:
|
||||
TouchpadInputDevice& fTarget;
|
||||
BString fPath;
|
||||
int fDevice;
|
||||
|
||||
private:
|
||||
TouchpadInputDevice& fTarget;
|
||||
BString fPath;
|
||||
int fDevice;
|
||||
input_device_ref fDeviceRef;
|
||||
mouse_settings fSettings;
|
||||
bool fDeviceRemapsButtons;
|
||||
|
||||
input_device_ref fDeviceRef;
|
||||
mouse_settings fSettings;
|
||||
bool fDeviceRemapsButtons;
|
||||
thread_id fThread;
|
||||
volatile bool fActive;
|
||||
volatile bool fUpdateSettings;
|
||||
|
||||
thread_id fThread;
|
||||
volatile bool fActive;
|
||||
|
||||
bool fIsTouchpad;
|
||||
touchpad_settings fTouchpadSettings;
|
||||
bool fIsTouchpad;
|
||||
touchpad_settings fTouchpadSettings;
|
||||
BMessage* fTouchpadSettingsMessage;
|
||||
BLocker fTouchpadSettingsLock;
|
||||
};
|
||||
|
||||
|
||||
@ -114,7 +122,10 @@ TouchpadDevice::TouchpadDevice(TouchpadInputDevice& target,
|
||||
fDeviceRemapsButtons(false),
|
||||
fThread(-1),
|
||||
fActive(false),
|
||||
fIsTouchpad(false)
|
||||
fUpdateSettings(false),
|
||||
fIsTouchpad(false),
|
||||
fTouchpadSettingsMessage(NULL),
|
||||
fTouchpadSettingsLock("Touchpad settings lock")
|
||||
{
|
||||
fPath = driverPath;
|
||||
|
||||
@ -137,16 +148,8 @@ TouchpadDevice::~TouchpadDevice()
|
||||
Stop();
|
||||
|
||||
free(fDeviceRef.name);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TouchpadDevice::_GetSettingsPath(BPath &path)
|
||||
{
|
||||
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
return path.Append(TOUCHPAD_SETTINGS_FILE);
|
||||
delete fTouchpadSettingsMessage;
|
||||
}
|
||||
|
||||
|
||||
@ -154,36 +157,15 @@ status_t
|
||||
TouchpadDevice::Start()
|
||||
{
|
||||
fDevice = open(fPath.String(), O_RDWR);
|
||||
if (fDevice < 0)
|
||||
return errno;
|
||||
|
||||
// touchpad settings
|
||||
if (ioctl(fDevice, MS_IS_TOUCHPAD, NULL) == B_OK) {
|
||||
LOG("is touchpad %s\n", fPath.String());
|
||||
fIsTouchpad = true;
|
||||
}
|
||||
|
||||
fTouchpadSettings = kDefaultTouchpadSettings;
|
||||
|
||||
BPath path;
|
||||
status_t status = _GetSettingsPath(path);
|
||||
BFile settingsFile(path.Path(), B_READ_ONLY);
|
||||
if (status == B_OK && settingsFile.InitCheck() == B_OK) {
|
||||
if (settingsFile.Read(&fTouchpadSettings, sizeof(touchpad_settings))
|
||||
!= sizeof(touchpad_settings)) {
|
||||
LOG("failed to load settings\n");
|
||||
}
|
||||
}
|
||||
|
||||
UpdateTouchpadSettings();
|
||||
UpdateSettings();
|
||||
// let the control thread handle any error on opening the device
|
||||
|
||||
char threadName[B_OS_NAME_LENGTH];
|
||||
snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", fDeviceRef.name);
|
||||
|
||||
fThread = spawn_thread(_ThreadFunction, threadName,
|
||||
fThread = spawn_thread(_ControlThreadEntry, threadName,
|
||||
kMouseThreadPriority, (void*)this);
|
||||
|
||||
status_t status;
|
||||
if (fThread < B_OK)
|
||||
status = fThread;
|
||||
else {
|
||||
@ -225,83 +207,97 @@ TouchpadDevice::Stop()
|
||||
status_t
|
||||
TouchpadDevice::UpdateSettings()
|
||||
{
|
||||
// TODO: This is duplicated in MouseInputDevice.cpp -> Refactor
|
||||
if (fThread < 0)
|
||||
return B_ERROR;
|
||||
|
||||
CALLED();
|
||||
|
||||
// retrieve current values
|
||||
|
||||
if (get_mouse_map(&fSettings.map) != B_OK)
|
||||
LOG_ERR("error when get_mouse_map\n");
|
||||
else
|
||||
fDeviceRemapsButtons = ioctl(fDevice, MS_SET_MAP, &fSettings.map) == B_OK;
|
||||
|
||||
if (get_click_speed(&fSettings.click_speed) != B_OK)
|
||||
LOG_ERR("error when get_click_speed\n");
|
||||
else
|
||||
ioctl(fDevice, MS_SET_CLICKSPEED, &fSettings.click_speed);
|
||||
|
||||
if (get_mouse_speed(&fSettings.accel.speed) != B_OK)
|
||||
LOG_ERR("error when get_mouse_speed\n");
|
||||
else {
|
||||
if (get_mouse_acceleration(&fSettings.accel.accel_factor) != B_OK)
|
||||
LOG_ERR("error when get_mouse_acceleration\n");
|
||||
else {
|
||||
mouse_accel accel;
|
||||
ioctl(fDevice, MS_GET_ACCEL, &accel);
|
||||
accel.speed = fSettings.accel.speed;
|
||||
accel.accel_factor = fSettings.accel.accel_factor;
|
||||
ioctl(fDevice, MS_SET_ACCEL, &fSettings.accel);
|
||||
}
|
||||
}
|
||||
|
||||
if (get_mouse_type(&fSettings.type) != B_OK)
|
||||
LOG_ERR("error when get_mouse_type\n");
|
||||
else
|
||||
ioctl(fDevice, MS_SET_TYPE, &fSettings.type);
|
||||
// trigger updating the settings in the control thread
|
||||
fUpdateSettings = true;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TouchpadDevice::ReadTouchpadSettingsMsg(BMessage* msg)
|
||||
TouchpadDevice::UpdateTouchpadSettings(const BMessage* message)
|
||||
{
|
||||
msg->FindBool("scroll_twofinger",
|
||||
&(fTouchpadSettings.scroll_twofinger));
|
||||
msg->FindBool("scroll_multifinger",
|
||||
&(fTouchpadSettings.scroll_multifinger));
|
||||
msg->FindFloat("scroll_rightrange",
|
||||
&(fTouchpadSettings.scroll_rightrange));
|
||||
msg->FindFloat("scroll_bottomrange",
|
||||
&(fTouchpadSettings.scroll_bottomrange));
|
||||
msg->FindInt16("scroll_xstepsize",
|
||||
(int16*)&(fTouchpadSettings.scroll_xstepsize));
|
||||
msg->FindInt16("scroll_ystepsize",
|
||||
(int16*)&(fTouchpadSettings.scroll_ystepsize));
|
||||
msg->FindInt8("scroll_acceleration",
|
||||
(int8*)&(fTouchpadSettings.scroll_acceleration));
|
||||
msg->FindInt8("tapgesture_sensibility",
|
||||
(int8*)&(fTouchpadSettings.tapgesture_sensibility));
|
||||
if (fThread < 0)
|
||||
return B_ERROR;
|
||||
|
||||
BAutolock _(fTouchpadSettingsLock);
|
||||
|
||||
// trigger updating the settings in the control thread
|
||||
fUpdateSettings = true;
|
||||
|
||||
delete fTouchpadSettingsMessage;
|
||||
fTouchpadSettingsMessage = new BMessage(*message);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TouchpadDevice::UpdateTouchpadSettings()
|
||||
char *
|
||||
TouchpadDevice::_BuildShortName() const
|
||||
{
|
||||
if (fIsTouchpad) {
|
||||
ioctl(fDevice, MS_SET_TOUCHPAD_SETTINGS, &fTouchpadSettings);
|
||||
return B_OK;
|
||||
}
|
||||
return B_ERROR;
|
||||
BString string(fPath);
|
||||
BString name;
|
||||
|
||||
int32 slash = string.FindLast("/");
|
||||
string.CopyInto(name, slash + 1, string.Length() - slash);
|
||||
//int32 index = atoi(name.String()) + 1;
|
||||
|
||||
BString final = "Touchpad ";
|
||||
final += name;
|
||||
|
||||
LOG("NAME %s, %s\n", final.String(), fPath.String());
|
||||
|
||||
return strdup(final.String());
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - control thread
|
||||
|
||||
|
||||
status_t
|
||||
TouchpadDevice::_ControlThreadEntry(void* arg)
|
||||
{
|
||||
TouchpadDevice* device = (TouchpadDevice*)arg;
|
||||
device->_ControlThread();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TouchpadDevice::_Run()
|
||||
TouchpadDevice::_ControlThread()
|
||||
{
|
||||
if (fDevice < 0) {
|
||||
_ControlThreadCleanup();
|
||||
// TOAST!
|
||||
return;
|
||||
}
|
||||
|
||||
// touchpad settings
|
||||
if (ioctl(fDevice, MS_IS_TOUCHPAD, NULL) == B_OK) {
|
||||
LOG("is touchpad %s\n", fPath.String());
|
||||
fIsTouchpad = true;
|
||||
}
|
||||
|
||||
fTouchpadSettings = kDefaultTouchpadSettings;
|
||||
|
||||
{
|
||||
BPath path;
|
||||
status_t status = _GetSettingsPath(path);
|
||||
BFile settingsFile(path.Path(), B_READ_ONLY);
|
||||
if (status == B_OK && settingsFile.InitCheck() == B_OK) {
|
||||
if (settingsFile.Read(&fTouchpadSettings, sizeof(touchpad_settings))
|
||||
!= sizeof(touchpad_settings)) {
|
||||
LOG("failed to load settings\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_UpdateTouchpadSettings();
|
||||
_UpdateSettings();
|
||||
|
||||
// TODO: Exact duplicate of MouseDevice::_Run() -> Refactor
|
||||
uint32 lastButtons = 0;
|
||||
|
||||
@ -310,20 +306,24 @@ TouchpadDevice::_Run()
|
||||
memset(&movements, 0, sizeof(movements));
|
||||
|
||||
if (ioctl(fDevice, MS_READ, &movements) != B_OK) {
|
||||
if (fActive) {
|
||||
fThread = -1;
|
||||
fTarget._RemoveDevice(fPath.String());
|
||||
} else {
|
||||
// In case active is already false, another thread
|
||||
// waits for this thread to quit, and may already hold
|
||||
// locks that _RemoveDevice() wants to acquire. In another
|
||||
// words, the device is already being removed, so we simply
|
||||
// quit here.
|
||||
}
|
||||
_ControlThreadCleanup();
|
||||
// TOAST!
|
||||
return;
|
||||
}
|
||||
|
||||
// update the settings if necessary
|
||||
if (fUpdateSettings) {
|
||||
fUpdateSettings = false;
|
||||
BAutolock _(fTouchpadSettingsLock);
|
||||
if (fTouchpadSettingsMessage) {
|
||||
_ReadTouchpadSettingsMsg(fTouchpadSettingsMessage);
|
||||
_UpdateTouchpadSettings();
|
||||
delete fTouchpadSettingsMessage;
|
||||
fTouchpadSettingsMessage = NULL;
|
||||
} else
|
||||
_UpdateSettings();
|
||||
}
|
||||
|
||||
uint32 buttons = lastButtons ^ movements.buttons;
|
||||
|
||||
uint32 remappedButtons = _RemapButtons(movements.buttons);
|
||||
@ -377,15 +377,110 @@ TouchpadDevice::_Run()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TouchpadDevice::_ThreadFunction(void* arg)
|
||||
void
|
||||
TouchpadDevice::_ControlThreadCleanup()
|
||||
{
|
||||
TouchpadDevice* device = (TouchpadDevice*)arg;
|
||||
device->_Run();
|
||||
// NOTE: Only executed when the control thread detected an error
|
||||
// and from within the control thread!
|
||||
|
||||
if (fActive) {
|
||||
fThread = -1;
|
||||
fTarget._RemoveDevice(fPath.String());
|
||||
} else {
|
||||
// In case active is already false, another thread
|
||||
// waits for this thread to quit, and may already hold
|
||||
// locks that _RemoveDevice() wants to acquire. In another
|
||||
// words, the device is already being removed, so we simply
|
||||
// quit here.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TouchpadDevice::_UpdateSettings()
|
||||
{
|
||||
// TODO: This is duplicated in MouseInputDevice.cpp -> Refactor
|
||||
|
||||
CALLED();
|
||||
|
||||
// retrieve current values
|
||||
|
||||
if (get_mouse_map(&fSettings.map) != B_OK)
|
||||
LOG_ERR("error when get_mouse_map\n");
|
||||
else
|
||||
fDeviceRemapsButtons = ioctl(fDevice, MS_SET_MAP, &fSettings.map) == B_OK;
|
||||
|
||||
if (get_click_speed(&fSettings.click_speed) != B_OK)
|
||||
LOG_ERR("error when get_click_speed\n");
|
||||
else
|
||||
ioctl(fDevice, MS_SET_CLICKSPEED, &fSettings.click_speed);
|
||||
|
||||
if (get_mouse_speed(&fSettings.accel.speed) != B_OK)
|
||||
LOG_ERR("error when get_mouse_speed\n");
|
||||
else {
|
||||
if (get_mouse_acceleration(&fSettings.accel.accel_factor) != B_OK)
|
||||
LOG_ERR("error when get_mouse_acceleration\n");
|
||||
else {
|
||||
mouse_accel accel;
|
||||
ioctl(fDevice, MS_GET_ACCEL, &accel);
|
||||
accel.speed = fSettings.accel.speed;
|
||||
accel.accel_factor = fSettings.accel.accel_factor;
|
||||
ioctl(fDevice, MS_SET_ACCEL, &fSettings.accel);
|
||||
}
|
||||
}
|
||||
|
||||
if (get_mouse_type(&fSettings.type) != B_OK)
|
||||
LOG_ERR("error when get_mouse_type\n");
|
||||
else
|
||||
ioctl(fDevice, MS_SET_TYPE, &fSettings.type);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TouchpadDevice::_GetSettingsPath(BPath &path)
|
||||
{
|
||||
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
return path.Append(TOUCHPAD_SETTINGS_FILE);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TouchpadDevice::_ReadTouchpadSettingsMsg(BMessage* message)
|
||||
{
|
||||
message->FindBool("scroll_twofinger",
|
||||
&(fTouchpadSettings.scroll_twofinger));
|
||||
message->FindBool("scroll_multifinger",
|
||||
&(fTouchpadSettings.scroll_multifinger));
|
||||
message->FindFloat("scroll_rightrange",
|
||||
&(fTouchpadSettings.scroll_rightrange));
|
||||
message->FindFloat("scroll_bottomrange",
|
||||
&(fTouchpadSettings.scroll_bottomrange));
|
||||
message->FindInt16("scroll_xstepsize",
|
||||
(int16*)&(fTouchpadSettings.scroll_xstepsize));
|
||||
message->FindInt16("scroll_ystepsize",
|
||||
(int16*)&(fTouchpadSettings.scroll_ystepsize));
|
||||
message->FindInt8("scroll_acceleration",
|
||||
(int8*)&(fTouchpadSettings.scroll_acceleration));
|
||||
message->FindInt8("tapgesture_sensibility",
|
||||
(int8*)&(fTouchpadSettings.tapgesture_sensibility));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TouchpadDevice::_UpdateTouchpadSettings()
|
||||
{
|
||||
if (fIsTouchpad) {
|
||||
ioctl(fDevice, MS_SET_TOUCHPAD_SETTINGS, &fTouchpadSettings);
|
||||
return B_OK;
|
||||
}
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
BMessage*
|
||||
TouchpadDevice::_BuildMouseMessage(uint32 what, uint64 when, uint32 buttons,
|
||||
int32 deltaX, int32 deltaY) const
|
||||
@ -467,29 +562,13 @@ TouchpadDevice::_RemapButtons(uint32 buttons) const
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
TouchpadDevice::_BuildShortName() const
|
||||
{
|
||||
BString string(fPath);
|
||||
BString name;
|
||||
|
||||
int32 slash = string.FindLast("/");
|
||||
string.CopyInto(name, slash + 1, string.Length() - slash);
|
||||
//int32 index = atoi(name.String()) + 1;
|
||||
|
||||
BString final = "Touchpad ";
|
||||
final += name;
|
||||
|
||||
LOG("NAME %s, %s\n", final.String(), fPath.String());
|
||||
|
||||
return strdup(final.String());
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
TouchpadInputDevice::TouchpadInputDevice()
|
||||
:
|
||||
fDevices(2, true),
|
||||
fDeviceListLock("TouchpadInputDevice list")
|
||||
{
|
||||
CALLED();
|
||||
|
||||
@ -545,10 +624,8 @@ TouchpadInputDevice::Control(const char* name, void* cookie,
|
||||
if (command == B_NODE_MONITOR)
|
||||
return _HandleMonitor(message);
|
||||
|
||||
if (command == MS_SET_TOUCHPAD_SETTINGS) {
|
||||
device->ReadTouchpadSettingsMsg(message);
|
||||
return device->UpdateTouchpadSettings();
|
||||
}
|
||||
if (command == MS_SET_TOUCHPAD_SETTINGS)
|
||||
return device->UpdateTouchpadSettings(message);
|
||||
|
||||
if (command >= B_MOUSE_TYPE_CHANGED
|
||||
&& command <= B_MOUSE_ACCELERATION_CHANGED)
|
||||
@ -602,7 +679,7 @@ TouchpadInputDevice::_RecursiveScan(const char* directory)
|
||||
|
||||
|
||||
TouchpadDevice*
|
||||
TouchpadInputDevice::_FindDevice(const char *path)
|
||||
TouchpadInputDevice::_FindDevice(const char *path) const
|
||||
{
|
||||
CALLED();
|
||||
|
||||
@ -621,6 +698,10 @@ TouchpadInputDevice::_AddDevice(const char *path)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
BAutolock _(fDeviceListLock);
|
||||
|
||||
_RemoveDevice(path);
|
||||
|
||||
TouchpadDevice* device = new (std::nothrow) TouchpadDevice(*this, path);
|
||||
if (!device) {
|
||||
LOG("No memory\n");
|
||||
@ -647,6 +728,8 @@ TouchpadInputDevice::_RemoveDevice(const char *path)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
BAutolock _(fDeviceListLock);
|
||||
|
||||
TouchpadDevice* device = _FindDevice(path);
|
||||
if (device == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <InputServerDevice.h>
|
||||
#include <InterfaceDefs.h>
|
||||
#include <Locker.h>
|
||||
|
||||
#include <ObjectList.h>
|
||||
|
||||
@ -41,11 +42,12 @@ public:
|
||||
status_t _HandleMonitor(BMessage* message);
|
||||
void _RecursiveScan(const char* directory);
|
||||
|
||||
TouchpadDevice* _FindDevice(const char* path);
|
||||
TouchpadDevice* _FindDevice(const char* path) const;
|
||||
status_t _AddDevice(const char* path);
|
||||
status_t _RemoveDevice(const char* path);
|
||||
|
||||
BObjectList<TouchpadDevice> fDevices;
|
||||
BLocker fDeviceListLock;
|
||||
};
|
||||
|
||||
extern "C" BInputServerDevice* instantiate_input_device();
|
||||
|
Loading…
Reference in New Issue
Block a user