123b47e0bSJérôme Duval /* 223b47e0bSJérôme Duval * Copyright 2004-2006, Haiku. 323b47e0bSJérôme Duval * Distributed under the terms of the MIT License. 423b47e0bSJérôme Duval * 523b47e0bSJérôme Duval * Authors: 623b47e0bSJérôme Duval * Stefano Ceccherini 723b47e0bSJérôme Duval */ 833efb919SStefano Ceccherini 933efb919SStefano Ceccherini 1061d7deeeSJérôme Duval #include "MouseInputDevice.h" 11fc2045eeSJérôme Duval #include "kb_mouse_settings.h" 12fc2045eeSJérôme Duval #include "kb_mouse_driver.h" 1361d7deeeSJérôme Duval 14c2fbfb71SJérôme Duval #include <Debug.h> 1533efb919SStefano Ceccherini #include <Directory.h> 1633efb919SStefano Ceccherini #include <Entry.h> 1733efb919SStefano Ceccherini #include <NodeMonitor.h> 1833efb919SStefano Ceccherini #include <Path.h> 1933efb919SStefano Ceccherini #include <String.h> 20*61604e48SAxel Dörfler #include <View.h> 21*61604e48SAxel Dörfler 22*61604e48SAxel Dörfler #include <errno.h> 23*61604e48SAxel Dörfler #include <new> 24*61604e48SAxel Dörfler #include <stdio.h> 25*61604e48SAxel Dörfler #include <stdlib.h> 26*61604e48SAxel Dörfler #include <unistd.h> 2733efb919SStefano Ceccherini 283aa69c78SStefano Ceccherini #if DEBUG 29c2fbfb71SJérôme Duval FILE *MouseInputDevice::sLogFile = NULL; 30*61604e48SAxel Dörfler # define LOG_ERR(text...) LOG(text) 313aa69c78SStefano Ceccherini #else 32c2fbfb71SJérôme Duval # define LOG(text...) 33c2fbfb71SJérôme Duval # define LOG_ERR(text...) fprintf(stderr, text) 343aa69c78SStefano Ceccherini #endif 353aa69c78SStefano Ceccherini 36c2fbfb71SJérôme Duval #define CALLED() LOG("%s\n", __PRETTY_FUNCTION__) 3733efb919SStefano Ceccherini 3823b47e0bSJérôme Duval #ifndef B_FIRST_REAL_TIME_PRIORITY 3923b47e0bSJérôme Duval # define B_FIRST_REAL_TIME_PRIORITY B_REAL_TIME_DISPLAY_PRIORITY 4023b47e0bSJérôme Duval #endif 41*61604e48SAxel Dörfler 4233efb919SStefano Ceccherini const static uint32 kMouseThreadPriority = B_FIRST_REAL_TIME_PRIORITY + 4; 4333efb919SStefano Ceccherini const static char *kMouseDevicesDirectory = "/dev/input/mouse"; 4433efb919SStefano Ceccherini 4533efb919SStefano Ceccherini // "/dev/" is automatically prepended by StartMonitoringDevice() 46f0bac935SJérôme Duval const static char *kMouseDevicesDirectoryPS2 = "input/mouse/ps2"; 4733efb919SStefano Ceccherini const static char *kMouseDevicesDirectoryUSB = "input/mouse/usb"; 4833efb919SStefano Ceccherini 49*61604e48SAxel Dörfler class MouseDevice { 50*61604e48SAxel Dörfler public: 51*61604e48SAxel Dörfler MouseDevice(BInputServerDevice& target, const char* path); 52*61604e48SAxel Dörfler ~MouseDevice(); 5333efb919SStefano Ceccherini 54*61604e48SAxel Dörfler status_t Start(); 55*61604e48SAxel Dörfler void Stop(); 56*61604e48SAxel Dörfler 57*61604e48SAxel Dörfler status_t UpdateSettings(); 58*61604e48SAxel Dörfler 59*61604e48SAxel Dörfler const char* Path() const { return fPath.String(); } 60*61604e48SAxel Dörfler input_device_ref* DeviceRef() { return &fDeviceRef; } 61*61604e48SAxel Dörfler 62*61604e48SAxel Dörfler private: 63*61604e48SAxel Dörfler void _Run(); 64*61604e48SAxel Dörfler static status_t _ThreadFunction(void *arg); 65*61604e48SAxel Dörfler 66*61604e48SAxel Dörfler BMessage* _BuildMouseMessage(uint32 what, uint64 when, uint32 buttons, 67*61604e48SAxel Dörfler int32 deltaX, int32 deltaY) const; 68*61604e48SAxel Dörfler void _ComputeAcceleration(const mouse_movement& movements, 69*61604e48SAxel Dörfler int32& deltaX, int32& deltaY) const; 70*61604e48SAxel Dörfler uint32 _RemapButtons(uint32 buttons) const; 71*61604e48SAxel Dörfler 72*61604e48SAxel Dörfler char* _BuildShortName() const; 73*61604e48SAxel Dörfler 74*61604e48SAxel Dörfler private: 75*61604e48SAxel Dörfler BInputServerDevice& fTarget; 76*61604e48SAxel Dörfler BString fPath; 77*61604e48SAxel Dörfler int fDevice; 78*61604e48SAxel Dörfler 79*61604e48SAxel Dörfler input_device_ref fDeviceRef; 80*61604e48SAxel Dörfler mouse_settings fSettings; 81*61604e48SAxel Dörfler bool fDeviceRemapsButtons; 82*61604e48SAxel Dörfler 83*61604e48SAxel Dörfler thread_id fThread; 84*61604e48SAxel Dörfler volatile bool fActive; 850dbc4befSStefano Ceccherini }; 860dbc4befSStefano Ceccherini 870dbc4befSStefano Ceccherini 88*61604e48SAxel Dörfler #if DEBUG 89*61604e48SAxel Dörfler inline void 90*61604e48SAxel Dörfler LOG(const char *fmt, ...) 91*61604e48SAxel Dörfler { 92*61604e48SAxel Dörfler char buf[1024]; 93*61604e48SAxel Dörfler va_list ap; 94*61604e48SAxel Dörfler va_start(ap, fmt); 95*61604e48SAxel Dörfler vsprintf(buf, fmt, ap); va_end(ap); 96*61604e48SAxel Dörfler fputs(buf, MouseInputDevice::sLogFile); fflush(MouseInputDevice::sLogFile); 97*61604e48SAxel Dörfler } 98*61604e48SAxel Dörfler #endif 994c0af4a8SStefano Ceccherini 1004c0af4a8SStefano Ceccherini 101*61604e48SAxel Dörfler extern "C" BInputServerDevice * 10261d7deeeSJérôme Duval instantiate_input_device() 10361d7deeeSJérôme Duval { 10461d7deeeSJérôme Duval return new MouseInputDevice(); 10561d7deeeSJérôme Duval } 10661d7deeeSJérôme Duval 10761d7deeeSJérôme Duval 108*61604e48SAxel Dörfler // #pragma mark - 109*61604e48SAxel Dörfler 110*61604e48SAxel Dörfler 111*61604e48SAxel Dörfler MouseDevice::MouseDevice(BInputServerDevice& target, const char *driverPath) 112*61604e48SAxel Dörfler : 113*61604e48SAxel Dörfler fTarget(target), 114*61604e48SAxel Dörfler fDevice(-1), 115*61604e48SAxel Dörfler fThread(-1), 116*61604e48SAxel Dörfler fActive(false) 11761d7deeeSJérôme Duval { 118*61604e48SAxel Dörfler fPath = driverPath; 119*61604e48SAxel Dörfler 120*61604e48SAxel Dörfler fDeviceRef.name = _BuildShortName(); 121*61604e48SAxel Dörfler fDeviceRef.type = B_POINTING_DEVICE; 122*61604e48SAxel Dörfler fDeviceRef.cookie = this; 123*61604e48SAxel Dörfler 124*61604e48SAxel Dörfler #ifdef HAIKU_TARGET_PLATFORM_HAIKU 125*61604e48SAxel Dörfler fSettings.map.button[0] = B_PRIMARY_MOUSE_BUTTON; 126*61604e48SAxel Dörfler fSettings.map.button[1] = B_SECONDARY_MOUSE_BUTTON; 127*61604e48SAxel Dörfler fSettings.map.button[2] = B_TERTIARY_MOUSE_BUTTON; 1283aa69c78SStefano Ceccherini #endif 12933efb919SStefano Ceccherini 130*61604e48SAxel Dörfler fDeviceRemapsButtons = false; 131*61604e48SAxel Dörfler }; 13261d7deeeSJérôme Duval 13361d7deeeSJérôme Duval 134*61604e48SAxel Dörfler MouseDevice::~MouseDevice() 13561d7deeeSJérôme Duval { 136*61604e48SAxel Dörfler if (fActive) 137*61604e48SAxel Dörfler Stop(); 13861d7deeeSJérôme Duval 139*61604e48SAxel Dörfler free(fDeviceRef.name); 14061d7deeeSJérôme Duval } 14161d7deeeSJérôme Duval 14261d7deeeSJérôme Duval 14361d7deeeSJérôme Duval status_t 144*61604e48SAxel Dörfler MouseDevice::Start() 14553d77642SJérôme Duval { 146*61604e48SAxel Dörfler fDevice = open(fPath.String(), O_RDWR); 147*61604e48SAxel Dörfler if (fDevice < 0) 148*61604e48SAxel Dörfler return errno; 14933efb919SStefano Ceccherini 150*61604e48SAxel Dörfler UpdateSettings(); 15133efb919SStefano Ceccherini 15233efb919SStefano Ceccherini char threadName[B_OS_NAME_LENGTH]; 153*61604e48SAxel Dörfler snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", fDeviceRef.name); 15433efb919SStefano Ceccherini 155*61604e48SAxel Dörfler fThread = spawn_thread(_ThreadFunction, threadName, 156*61604e48SAxel Dörfler kMouseThreadPriority, (void *)this); 1574c0af4a8SStefano Ceccherini 15833efb919SStefano Ceccherini status_t status; 159*61604e48SAxel Dörfler if (fThread < B_OK) 160*61604e48SAxel Dörfler status = fThread; 161*61604e48SAxel Dörfler else { 162*61604e48SAxel Dörfler fActive = true; 163*61604e48SAxel Dörfler status = resume_thread(fThread); 164*61604e48SAxel Dörfler } 16533efb919SStefano Ceccherini 166*61604e48SAxel Dörfler if (status < B_OK) { 167*61604e48SAxel Dörfler LOG_ERR("%s: can't spawn/resume watching thread: %s\n", 168*61604e48SAxel Dörfler fDeviceRef.name, strerror(status)); 169*61604e48SAxel Dörfler close(fDevice); 170*61604e48SAxel Dörfler return status; 171*61604e48SAxel Dörfler } 172*61604e48SAxel Dörfler 173c2fbfb71SJérôme Duval return B_OK; 17461d7deeeSJérôme Duval } 17561d7deeeSJérôme Duval 17661d7deeeSJérôme Duval 177c2fbfb71SJérôme Duval void 178*61604e48SAxel Dörfler MouseDevice::Stop() 179*61604e48SAxel Dörfler { 180*61604e48SAxel Dörfler fActive = false; 181*61604e48SAxel Dörfler // this will stop the thread as soon as it reads the next packet 182*61604e48SAxel Dörfler 183*61604e48SAxel Dörfler if (fThread >= B_OK) { 184*61604e48SAxel Dörfler // unblock the thread, which might wait on a semaphore. 185*61604e48SAxel Dörfler suspend_thread(fThread); 186*61604e48SAxel Dörfler resume_thread(fThread); 187*61604e48SAxel Dörfler 188*61604e48SAxel Dörfler status_t dummy; 189*61604e48SAxel Dörfler wait_for_thread(fThread, &dummy); 190*61604e48SAxel Dörfler } 191*61604e48SAxel Dörfler 192*61604e48SAxel Dörfler close(fDevice); 193*61604e48SAxel Dörfler } 194*61604e48SAxel Dörfler 195*61604e48SAxel Dörfler 196*61604e48SAxel Dörfler void 197*61604e48SAxel Dörfler MouseDevice::_Run() 198*61604e48SAxel Dörfler { 199*61604e48SAxel Dörfler uint32 lastButtons = 0; 200*61604e48SAxel Dörfler 201*61604e48SAxel Dörfler while (fActive) { 202*61604e48SAxel Dörfler mouse_movement movements; 203*61604e48SAxel Dörfler memset(&movements, 0, sizeof(movements)); 204*61604e48SAxel Dörfler 205*61604e48SAxel Dörfler if (ioctl(fDevice, MS_READ, &movements) != B_OK) 206*61604e48SAxel Dörfler return; 207*61604e48SAxel Dörfler 208*61604e48SAxel Dörfler uint32 buttons = lastButtons ^ movements.buttons; 209*61604e48SAxel Dörfler 210*61604e48SAxel Dörfler uint32 remappedButtons = _RemapButtons(movements.buttons); 211*61604e48SAxel Dörfler int32 deltaX, deltaY; 212*61604e48SAxel Dörfler _ComputeAcceleration(movements, deltaX, deltaY); 213*61604e48SAxel Dörfler 214*61604e48SAxel Dörfler LOG("%s: buttons: 0x%lx, x: %ld, y: %ld, clicks:%ld, wheel_x:%ld, wheel_y:%ld\n", 215*61604e48SAxel Dörfler device->device_ref.name, movements.buttons, movements.xdelta, movements.ydelta, 216*61604e48SAxel Dörfler movements.clicks, movements.wheel_xdelta, movements.wheel_ydelta); 217*61604e48SAxel Dörfler LOG("%s: x: %ld, y: %ld\n", device->device_ref.name, deltaX, deltaY); 218*61604e48SAxel Dörfler 219*61604e48SAxel Dörfler BMessage *message = NULL; 220*61604e48SAxel Dörfler 221*61604e48SAxel Dörfler // Send single messages for each event 222*61604e48SAxel Dörfler 223*61604e48SAxel Dörfler if (movements.xdelta != 0 || movements.ydelta != 0) { 224*61604e48SAxel Dörfler BMessage* message = _BuildMouseMessage(B_MOUSE_MOVED, movements.timestamp, 225*61604e48SAxel Dörfler remappedButtons, deltaX, deltaY); 226*61604e48SAxel Dörfler if (message != NULL) 227*61604e48SAxel Dörfler fTarget.EnqueueMessage(message); 228*61604e48SAxel Dörfler } 229*61604e48SAxel Dörfler 230*61604e48SAxel Dörfler if (buttons != 0) { 231*61604e48SAxel Dörfler bool pressedButton = (buttons & movements.buttons) > 0; 232*61604e48SAxel Dörfler BMessage* message = _BuildMouseMessage( 233*61604e48SAxel Dörfler pressedButton ? B_MOUSE_DOWN : B_MOUSE_UP, 234*61604e48SAxel Dörfler movements.timestamp, remappedButtons, deltaX, deltaY); 235*61604e48SAxel Dörfler if (message != NULL) { 236*61604e48SAxel Dörfler if (pressedButton) { 237*61604e48SAxel Dörfler message->AddInt32("clicks", movements.clicks); 238*61604e48SAxel Dörfler LOG("B_MOUSE_DOWN\n"); 239*61604e48SAxel Dörfler } else 240*61604e48SAxel Dörfler LOG("B_MOUSE_UP\n"); 241*61604e48SAxel Dörfler 242*61604e48SAxel Dörfler fTarget.EnqueueMessage(message); 243*61604e48SAxel Dörfler lastButtons = movements.buttons; 244*61604e48SAxel Dörfler } 245*61604e48SAxel Dörfler } 246*61604e48SAxel Dörfler 247*61604e48SAxel Dörfler if ((movements.wheel_ydelta != 0) || (movements.wheel_xdelta != 0)) { 248*61604e48SAxel Dörfler message = new BMessage(B_MOUSE_WHEEL_CHANGED); 249*61604e48SAxel Dörfler if (message == NULL) 250*61604e48SAxel Dörfler continue; 251*61604e48SAxel Dörfler 252*61604e48SAxel Dörfler if (message->AddInt64("when", movements.timestamp) == B_OK 253*61604e48SAxel Dörfler && message->AddFloat("be:wheel_delta_x", movements.wheel_xdelta) == B_OK 254*61604e48SAxel Dörfler && message->AddFloat("be:wheel_delta_y", movements.wheel_ydelta) == B_OK) 255*61604e48SAxel Dörfler fTarget.EnqueueMessage(message); 256*61604e48SAxel Dörfler else 257*61604e48SAxel Dörfler delete message; 258*61604e48SAxel Dörfler } 259*61604e48SAxel Dörfler } 260*61604e48SAxel Dörfler } 261*61604e48SAxel Dörfler 262*61604e48SAxel Dörfler 263*61604e48SAxel Dörfler status_t 264*61604e48SAxel Dörfler MouseDevice::_ThreadFunction(void* arg) 265*61604e48SAxel Dörfler { 266*61604e48SAxel Dörfler MouseDevice* device = (MouseDevice *)arg; 267*61604e48SAxel Dörfler device->_Run(); 268*61604e48SAxel Dörfler return B_OK; 269*61604e48SAxel Dörfler } 270*61604e48SAxel Dörfler 271*61604e48SAxel Dörfler 272*61604e48SAxel Dörfler BMessage* 273*61604e48SAxel Dörfler MouseDevice::_BuildMouseMessage(uint32 what, uint64 when, uint32 buttons, 274*61604e48SAxel Dörfler int32 deltaX, int32 deltaY) const 275*61604e48SAxel Dörfler { 276*61604e48SAxel Dörfler BMessage* message = new BMessage(what); 277*61604e48SAxel Dörfler if (message == NULL) 278*61604e48SAxel Dörfler return NULL; 279*61604e48SAxel Dörfler 280*61604e48SAxel Dörfler if (message->AddInt64("when", when) < B_OK 281*61604e48SAxel Dörfler || message->AddInt32("buttons", buttons) < B_OK 282*61604e48SAxel Dörfler || message->AddInt32("x", deltaX) < B_OK 283*61604e48SAxel Dörfler || message->AddInt32("y", deltaY) < B_OK) { 284*61604e48SAxel Dörfler delete message; 285*61604e48SAxel Dörfler return NULL; 286*61604e48SAxel Dörfler } 287*61604e48SAxel Dörfler 288*61604e48SAxel Dörfler return message; 289*61604e48SAxel Dörfler } 290*61604e48SAxel Dörfler 291*61604e48SAxel Dörfler 292*61604e48SAxel Dörfler status_t 293*61604e48SAxel Dörfler MouseDevice::UpdateSettings() 29433efb919SStefano Ceccherini { 295c2fbfb71SJérôme Duval CALLED(); 296497d01f0SAxel Dörfler 297*61604e48SAxel Dörfler // retrieve current values 298c2fbfb71SJérôme Duval 299*61604e48SAxel Dörfler if (get_mouse_map(&fSettings.map) != B_OK) 300*61604e48SAxel Dörfler LOG_ERR("error when get_mouse_map\n"); 301c2fbfb71SJérôme Duval else 302*61604e48SAxel Dörfler fDeviceRemapsButtons = ioctl(fDevice, MS_SET_MAP, &fSettings.map) == B_OK; 303*61604e48SAxel Dörfler 304*61604e48SAxel Dörfler if (get_click_speed(&fSettings.click_speed) != B_OK) 305*61604e48SAxel Dörfler LOG_ERR("error when get_click_speed\n"); 306*61604e48SAxel Dörfler else 307*61604e48SAxel Dörfler ioctl(fDevice, MS_SET_CLICKSPEED, &fSettings.click_speed); 308*61604e48SAxel Dörfler 309*61604e48SAxel Dörfler if (get_mouse_speed(&fSettings.accel.speed) != B_OK) 310*61604e48SAxel Dörfler LOG_ERR("error when get_mouse_speed\n"); 311*61604e48SAxel Dörfler else { 312*61604e48SAxel Dörfler if (get_mouse_acceleration(&fSettings.accel.accel_factor) != B_OK) 313*61604e48SAxel Dörfler LOG_ERR("error when get_mouse_acceleration\n"); 314*61604e48SAxel Dörfler else { 315*61604e48SAxel Dörfler mouse_accel accel; 316*61604e48SAxel Dörfler ioctl(fDevice, MS_GET_ACCEL, &accel); 317*61604e48SAxel Dörfler accel.speed = fSettings.accel.speed; 318*61604e48SAxel Dörfler accel.accel_factor = fSettings.accel.accel_factor; 319*61604e48SAxel Dörfler ioctl(fDevice, MS_SET_ACCEL, &fSettings.accel); 32033efb919SStefano Ceccherini } 32133efb919SStefano Ceccherini } 32233efb919SStefano Ceccherini 323*61604e48SAxel Dörfler if (get_mouse_type(&fSettings.type) != B_OK) 324*61604e48SAxel Dörfler LOG_ERR("error when get_mouse_type\n"); 325*61604e48SAxel Dörfler else 326*61604e48SAxel Dörfler ioctl(fDevice, MS_SET_TYPE, &fSettings.type); 327*61604e48SAxel Dörfler 328*61604e48SAxel Dörfler return B_OK; 329*61604e48SAxel Dörfler 330*61604e48SAxel Dörfler } 331*61604e48SAxel Dörfler 332*61604e48SAxel Dörfler 333*61604e48SAxel Dörfler void 334*61604e48SAxel Dörfler MouseDevice::_ComputeAcceleration(const mouse_movement& movements, 335*61604e48SAxel Dörfler int32& deltaX, int32& deltaY) const 336*61604e48SAxel Dörfler { 337*61604e48SAxel Dörfler // TODO: add acceleration computing 338*61604e48SAxel Dörfler deltaX = movements.xdelta * fSettings.accel.speed >> 15; 339*61604e48SAxel Dörfler deltaY = movements.ydelta * fSettings.accel.speed >> 15; 340*61604e48SAxel Dörfler } 341*61604e48SAxel Dörfler 34233efb919SStefano Ceccherini 34323b47e0bSJérôme Duval uint32 344*61604e48SAxel Dörfler MouseDevice::_RemapButtons(uint32 buttons) const 34523b47e0bSJérôme Duval { 346*61604e48SAxel Dörfler if (fDeviceRemapsButtons) 34723b47e0bSJérôme Duval return buttons; 34823b47e0bSJérôme Duval 349*61604e48SAxel Dörfler uint32 newButtons = 0; 35023b47e0bSJérôme Duval for (int32 i = 0; buttons; i++) { 35123b47e0bSJérôme Duval if (buttons & 0x1) { 35223b47e0bSJérôme Duval #ifdef HAIKU_TARGET_PLATFORM_HAIKU 353*61604e48SAxel Dörfler newButtons |= fSettings.map.button[i]; 35423b47e0bSJérôme Duval #else 35523b47e0bSJérôme Duval if (i == 0) 356*61604e48SAxel Dörfler newButtons |= fSettings.map.left; 35723b47e0bSJérôme Duval if (i == 1) 358*61604e48SAxel Dörfler newButtons |= fSettings.map.right; 35923b47e0bSJérôme Duval if (i == 2) 360*61604e48SAxel Dörfler newButtons |= fSettings.map.middle; 36123b47e0bSJérôme Duval #endif 36223b47e0bSJérôme Duval } 36323b47e0bSJérôme Duval buttons >>= 1; 36423b47e0bSJérôme Duval } 36523b47e0bSJérôme Duval 366*61604e48SAxel Dörfler return newButtons; 36723b47e0bSJérôme Duval } 36823b47e0bSJérôme Duval 36923b47e0bSJérôme Duval 370*61604e48SAxel Dörfler char * 371*61604e48SAxel Dörfler MouseDevice::_BuildShortName() const 3724c0af4a8SStefano Ceccherini { 373*61604e48SAxel Dörfler BString string(fPath); 37433efb919SStefano Ceccherini BString name; 37533efb919SStefano Ceccherini 37633efb919SStefano Ceccherini int32 slash = string.FindLast("/"); 3777dcdcad2SJérôme Duval string.CopyInto(name, slash + 1, string.Length() - slash); 3787dcdcad2SJérôme Duval int32 index = atoi(name.String()) + 1; 37933efb919SStefano Ceccherini 3807dcdcad2SJérôme Duval int32 previousSlash = string.FindLast("/", slash); 3817dcdcad2SJérôme Duval string.CopyInto(name, previousSlash + 1, slash - previousSlash - 1); 382497d01f0SAxel Dörfler 383497d01f0SAxel Dörfler if (name == "ps2") 384497d01f0SAxel Dörfler name = "PS/2"; 385497d01f0SAxel Dörfler else 386497d01f0SAxel Dörfler name.Capitalize(); 387497d01f0SAxel Dörfler 3887dcdcad2SJérôme Duval name << " Mouse " << index; 38933efb919SStefano Ceccherini 39033efb919SStefano Ceccherini return strdup(name.String()); 39133efb919SStefano Ceccherini } 392*61604e48SAxel Dörfler 393*61604e48SAxel Dörfler 394*61604e48SAxel Dörfler // #pragma mark - 395*61604e48SAxel Dörfler 396*61604e48SAxel Dörfler 397*61604e48SAxel Dörfler MouseInputDevice::MouseInputDevice() 398*61604e48SAxel Dörfler { 399*61604e48SAxel Dörfler #if DEBUG 400*61604e48SAxel Dörfler sLogFile = fopen("/var/log/mouse_device_log.log", "a"); 401*61604e48SAxel Dörfler #endif 402*61604e48SAxel Dörfler CALLED(); 403*61604e48SAxel Dörfler 404*61604e48SAxel Dörfler StartMonitoringDevice(kMouseDevicesDirectoryPS2); 405*61604e48SAxel Dörfler StartMonitoringDevice(kMouseDevicesDirectoryUSB); 406*61604e48SAxel Dörfler 407*61604e48SAxel Dörfler _RecursiveScan(kMouseDevicesDirectory); 408*61604e48SAxel Dörfler } 409*61604e48SAxel Dörfler 410*61604e48SAxel Dörfler 411*61604e48SAxel Dörfler MouseInputDevice::~MouseInputDevice() 412*61604e48SAxel Dörfler { 413*61604e48SAxel Dörfler CALLED(); 414*61604e48SAxel Dörfler StopMonitoringDevice(kMouseDevicesDirectoryUSB); 415*61604e48SAxel Dörfler StopMonitoringDevice(kMouseDevicesDirectoryPS2); 416*61604e48SAxel Dörfler 417*61604e48SAxel Dörfler int32 count = fDevices.CountItems(); 418*61604e48SAxel Dörfler while (count-- > 0) { 419*61604e48SAxel Dörfler delete (MouseDevice *)fDevices.RemoveItem(count); 420*61604e48SAxel Dörfler } 421*61604e48SAxel Dörfler 422*61604e48SAxel Dörfler #if DEBUG 423*61604e48SAxel Dörfler fclose(sLogFile); 424*61604e48SAxel Dörfler #endif 425*61604e48SAxel Dörfler } 426*61604e48SAxel Dörfler 427*61604e48SAxel Dörfler 428*61604e48SAxel Dörfler status_t 429*61604e48SAxel Dörfler MouseInputDevice::InitCheck() 430*61604e48SAxel Dörfler { 431*61604e48SAxel Dörfler CALLED(); 432*61604e48SAxel Dörfler return B_OK; 433*61604e48SAxel Dörfler } 434*61604e48SAxel Dörfler 435*61604e48SAxel Dörfler 436*61604e48SAxel Dörfler status_t 437*61604e48SAxel Dörfler MouseInputDevice::Start(const char *name, void *cookie) 438*61604e48SAxel Dörfler { 439*61604e48SAxel Dörfler LOG("%s(%s)\n", __PRETTY_FUNCTION__, name); 440*61604e48SAxel Dörfler MouseDevice* device = (MouseDevice*)cookie; 441*61604e48SAxel Dörfler 442*61604e48SAxel Dörfler return device->Start(); 443*61604e48SAxel Dörfler } 444*61604e48SAxel Dörfler 445*61604e48SAxel Dörfler 446*61604e48SAxel Dörfler status_t 447*61604e48SAxel Dörfler MouseInputDevice::Stop(const char *name, void *cookie) 448*61604e48SAxel Dörfler { 449*61604e48SAxel Dörfler LOG("%s(%s)\n", __PRETTY_FUNCTION__, name); 450*61604e48SAxel Dörfler MouseDevice* device = (MouseDevice*)cookie; 451*61604e48SAxel Dörfler 452*61604e48SAxel Dörfler device->Stop(); 453*61604e48SAxel Dörfler return B_OK; 454*61604e48SAxel Dörfler } 455*61604e48SAxel Dörfler 456*61604e48SAxel Dörfler 457*61604e48SAxel Dörfler status_t 458*61604e48SAxel Dörfler MouseInputDevice::Control(const char* name, void* cookie, 459*61604e48SAxel Dörfler uint32 command, BMessage* message) 460*61604e48SAxel Dörfler { 461*61604e48SAxel Dörfler LOG("%s(%s, code: %lu)\n", __PRETTY_FUNCTION__, name, command); 462*61604e48SAxel Dörfler MouseDevice* device = (MouseDevice*)cookie; 463*61604e48SAxel Dörfler 464*61604e48SAxel Dörfler if (command == B_NODE_MONITOR) 465*61604e48SAxel Dörfler return _HandleMonitor(message); 466*61604e48SAxel Dörfler 467*61604e48SAxel Dörfler if (command >= B_MOUSE_TYPE_CHANGED 468*61604e48SAxel Dörfler && command <= B_MOUSE_ACCELERATION_CHANGED) 469*61604e48SAxel Dörfler return device->UpdateSettings(); 470*61604e48SAxel Dörfler 471*61604e48SAxel Dörfler return B_BAD_VALUE; 472*61604e48SAxel Dörfler } 473*61604e48SAxel Dörfler 474*61604e48SAxel Dörfler 475*61604e48SAxel Dörfler // TODO: Test this. USB doesn't work on my machine 476*61604e48SAxel Dörfler status_t 477*61604e48SAxel Dörfler MouseInputDevice::_HandleMonitor(BMessage* message) 478*61604e48SAxel Dörfler { 479*61604e48SAxel Dörfler CALLED(); 480*61604e48SAxel Dörfler 481*61604e48SAxel Dörfler int32 opcode; 482*61604e48SAxel Dörfler if (message->FindInt32("opcode", &opcode) < B_OK) 483*61604e48SAxel Dörfler return B_BAD_VALUE; 484*61604e48SAxel Dörfler 485*61604e48SAxel Dörfler if (opcode != B_ENTRY_CREATED && opcode != B_ENTRY_REMOVED) 486*61604e48SAxel Dörfler return B_OK; 487*61604e48SAxel Dörfler 488*61604e48SAxel Dörfler BEntry entry; 489*61604e48SAxel Dörfler BPath path; 490*61604e48SAxel Dörfler dev_t device; 491*61604e48SAxel Dörfler ino_t directory; 492*61604e48SAxel Dörfler const char *name; 493*61604e48SAxel Dörfler 494*61604e48SAxel Dörfler if (message->FindInt32("device", &device) < B_OK 495*61604e48SAxel Dörfler || message->FindInt64("directory", &directory) < B_OK 496*61604e48SAxel Dörfler || message->FindString("name", &name) < B_OK) 497*61604e48SAxel Dörfler return B_BAD_VALUE; 498*61604e48SAxel Dörfler 499*61604e48SAxel Dörfler entry_ref ref(device, directory, name); 500*61604e48SAxel Dörfler status_t status; 501*61604e48SAxel Dörfler 502*61604e48SAxel Dörfler if ((status = entry.SetTo(&ref)) != B_OK) 503*61604e48SAxel Dörfler return status; 504*61604e48SAxel Dörfler if ((status = entry.GetPath(&path)) != B_OK) 505*61604e48SAxel Dörfler return status; 506*61604e48SAxel Dörfler if ((status = path.InitCheck()) != B_OK) 507*61604e48SAxel Dörfler return status; 508*61604e48SAxel Dörfler 509*61604e48SAxel Dörfler if (opcode == B_ENTRY_CREATED) 510*61604e48SAxel Dörfler status = _AddDevice(path.Path()); 511*61604e48SAxel Dörfler else 512*61604e48SAxel Dörfler status = _RemoveDevice(path.Path()); 513*61604e48SAxel Dörfler 514*61604e48SAxel Dörfler return status; 515*61604e48SAxel Dörfler } 516*61604e48SAxel Dörfler 517*61604e48SAxel Dörfler 518*61604e48SAxel Dörfler MouseDevice* 519*61604e48SAxel Dörfler MouseInputDevice::_FindDevice(const char *path) 520*61604e48SAxel Dörfler { 521*61604e48SAxel Dörfler CALLED(); 522*61604e48SAxel Dörfler 523*61604e48SAxel Dörfler for (int32 i = fDevices.CountItems(); i-- > 0;) { 524*61604e48SAxel Dörfler MouseDevice* device = (MouseDevice*)fDevices.ItemAt(i); 525*61604e48SAxel Dörfler if (!strcmp(device->Path(), path)) 526*61604e48SAxel Dörfler return device; 527*61604e48SAxel Dörfler } 528*61604e48SAxel Dörfler 529*61604e48SAxel Dörfler return NULL; 530*61604e48SAxel Dörfler } 531*61604e48SAxel Dörfler 532*61604e48SAxel Dörfler 533*61604e48SAxel Dörfler status_t 534*61604e48SAxel Dörfler MouseInputDevice::_AddDevice(const char *path) 535*61604e48SAxel Dörfler { 536*61604e48SAxel Dörfler CALLED(); 537*61604e48SAxel Dörfler 538*61604e48SAxel Dörfler MouseDevice* device = new (std::nothrow) MouseDevice(*this, path); 539*61604e48SAxel Dörfler if (!device) { 540*61604e48SAxel Dörfler LOG("No memory\n"); 541*61604e48SAxel Dörfler return B_NO_MEMORY; 542*61604e48SAxel Dörfler } 543*61604e48SAxel Dörfler 544*61604e48SAxel Dörfler if (!fDevices.AddItem(device)) { 545*61604e48SAxel Dörfler delete device; 546*61604e48SAxel Dörfler return B_NO_MEMORY; 547*61604e48SAxel Dörfler } 548*61604e48SAxel Dörfler 549*61604e48SAxel Dörfler input_device_ref *devices[2]; 550*61604e48SAxel Dörfler devices[0] = device->DeviceRef(); 551*61604e48SAxel Dörfler devices[1] = NULL; 552*61604e48SAxel Dörfler 553*61604e48SAxel Dörfler return RegisterDevices(devices); 554*61604e48SAxel Dörfler } 555*61604e48SAxel Dörfler 556*61604e48SAxel Dörfler 557*61604e48SAxel Dörfler status_t 558*61604e48SAxel Dörfler MouseInputDevice::_RemoveDevice(const char *path) 559*61604e48SAxel Dörfler { 560*61604e48SAxel Dörfler CALLED(); 561*61604e48SAxel Dörfler 562*61604e48SAxel Dörfler MouseDevice* device = _FindDevice(path); 563*61604e48SAxel Dörfler if (device == NULL) 564*61604e48SAxel Dörfler return B_ENTRY_NOT_FOUND; 565*61604e48SAxel Dörfler 566*61604e48SAxel Dörfler fDevices.RemoveItem(device); 567*61604e48SAxel Dörfler 568*61604e48SAxel Dörfler input_device_ref *devices[2]; 569*61604e48SAxel Dörfler devices[0] = device->DeviceRef(); 570*61604e48SAxel Dörfler devices[1] = NULL; 571*61604e48SAxel Dörfler 572*61604e48SAxel Dörfler UnregisterDevices(devices); 573*61604e48SAxel Dörfler 574*61604e48SAxel Dörfler delete device; 575*61604e48SAxel Dörfler return B_OK; 576*61604e48SAxel Dörfler } 577*61604e48SAxel Dörfler 578*61604e48SAxel Dörfler 579*61604e48SAxel Dörfler void 580*61604e48SAxel Dörfler MouseInputDevice::_RecursiveScan(const char* directory) 581*61604e48SAxel Dörfler { 582*61604e48SAxel Dörfler CALLED(); 583*61604e48SAxel Dörfler 584*61604e48SAxel Dörfler BEntry entry; 585*61604e48SAxel Dörfler BDirectory dir(directory); 586*61604e48SAxel Dörfler while (dir.GetNextEntry(&entry) == B_OK) { 587*61604e48SAxel Dörfler BPath path; 588*61604e48SAxel Dörfler entry.GetPath(&path); 589*61604e48SAxel Dörfler 590*61604e48SAxel Dörfler if (!strcmp(path.Leaf(), "serial")) { 591*61604e48SAxel Dörfler // skip serial 592*61604e48SAxel Dörfler continue; 593*61604e48SAxel Dörfler } 594*61604e48SAxel Dörfler 595*61604e48SAxel Dörfler if (entry.IsDirectory()) 596*61604e48SAxel Dörfler _RecursiveScan(path.Path()); 597*61604e48SAxel Dörfler else 598*61604e48SAxel Dörfler _AddDevice(path.Path()); 599*61604e48SAxel Dörfler } 600*61604e48SAxel Dörfler } 601*61604e48SAxel Dörfler 602