diff --git a/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.cpp b/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.cpp index df2cd23aad..18c5d90beb 100644 --- a/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.cpp +++ b/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.cpp @@ -26,9 +26,21 @@ /*****************************************************************************/ #include "KeyboardInputDevice.h" +#include +#include +#include +#include +#include #include #include +#define DEBUG 1 +#if DEBUG + #define LOG(text) fputs(text, sLogFile); fflush(sLogFile) +#else + #define LOG(text) +#endif + const static uint32 kSetLeds = 0x2711; const static uint32 kSetRepeatingKey = 0x2712; const static uint32 kSetNonRepeatingKey = 0x2713; @@ -36,6 +48,23 @@ const static uint32 kSetKeyRepeatRate = 0x2714; const static uint32 kSetKeyRepeatDelay = 0x2716; const static uint32 kGetNextKey = 0x270f; +const static uint32 kKeyboardThreadPriority = B_FIRST_REAL_TIME_PRIORITY + 4; +const static char *kKeyboardDevicesDirectory = "/dev/input/keyboard"; + +// "/dev/" is automatically prepended by StartMonitoringDevice() +const static char *kKeyboardDevicesDirectoryUSB = "input/keyboard/usb"; + +FILE *KeyboardInputDevice::sLogFile = NULL; + +struct keyboard_device { + KeyboardInputDevice *owner; + input_device_ref device_ref; + char path[B_PATH_NAME_LENGTH]; + int fd; + thread_id device_watcher; + kb_settings settings; + bool active; +}; extern "C" BInputServerDevice * @@ -46,34 +75,29 @@ instantiate_input_device() KeyboardInputDevice::KeyboardInputDevice() - : fThread(-1), - fQuit(false) { - fFd = open("dev/input/keyboard/ps2/0", O_RDWR); - if (fFd >= 0) - fThread = spawn_thread(DeviceWatcher, "keyboard watcher thread", - B_NORMAL_PRIORITY, this); - - fLogFile = fopen("/boot/home/device_log.log", "w"); + +#if DEBUG + if (sLogFile == NULL) + sLogFile = fopen("/var/log/keyboard_device_log.log", "a"); +#endif + + StartMonitoringDevice(kKeyboardDevicesDirectoryUSB); } KeyboardInputDevice::~KeyboardInputDevice() { - if (fThread >= 0) { - status_t dummy; - wait_for_thread(fThread, &dummy); - } + StopMonitoringDevice(kKeyboardDevicesDirectoryUSB); - if (fFd >= 0) - close(fFd); - - fclose(fLogFile); +#if DEBUG + fclose(sLogFile); +#endif } status_t -KeyboardInputDevice::InitFromSettings(uint32 opcode) +KeyboardInputDevice::InitFromSettings(void *cookie, uint32 opcode) { // retrieve current values @@ -84,38 +108,45 @@ KeyboardInputDevice::InitFromSettings(uint32 opcode) status_t KeyboardInputDevice::InitCheck() { - InitFromSettings(); - - input_device_ref keyboard1 = { "Keyboard 1", B_KEYBOARD_DEVICE, (void *)this }; - - input_device_ref *devices[2] = { &keyboard1, NULL }; - - if (fFd >= 0 && fThread >= 0) { - RegisterDevices(devices); - return BInputServerDevice::InitCheck(); - } - return B_ERROR; -} - - -status_t -KeyboardInputDevice::Start(const char *name, void *cookie) -{ - fputs("Start(", fLogFile); - fputs(name, fLogFile); - fputs(")\n", fLogFile); - resume_thread(fThread); + RecursiveScan(kKeyboardDevicesDirectory); return B_OK; } status_t -KeyboardInputDevice::Stop(const char *device, void *cookie) +KeyboardInputDevice::Start(const char *name, void *cookie) { - fputs("Stop()\n", fLogFile); + keyboard_device *device = (keyboard_device *)cookie; - suspend_thread(fThread); + char threadName[B_OS_NAME_LENGTH]; + snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", name); + + device->active = true; + device->device_watcher = spawn_thread(DeviceWatcher, threadName, + kKeyboardThreadPriority, device); + + resume_thread(device->device_watcher); + + return B_OK; +} + + +status_t +KeyboardInputDevice::Stop(const char *name, void *cookie) +{ + keyboard_device *device = (keyboard_device *)cookie; + + char log[128]; + snprintf(log, 128, "Stop(%s)\n", name); + + LOG(log); + + device->active = false; + if (device->device_watcher >= 0) { + status_t dummy; + wait_for_thread(device->device_watcher, &dummy); + } return B_OK; } @@ -125,13 +156,16 @@ status_t KeyboardInputDevice::Control(const char *name, void *cookie, uint32 command, BMessage *message) { - fputs("Control()\n", fLogFile); + char log[128]; + snprintf(log, 128, "Control(%s, code: %lu)\n", name, command); + + LOG(log); if (command == B_NODE_MONITOR) HandleMonitor(message); else if (command >= B_KEY_MAP_CHANGED && command <= B_KEY_REPEAT_RATE_CHANGED) { - InitFromSettings(command); + InitFromSettings(cookie, command); } return B_OK; } @@ -140,16 +174,135 @@ KeyboardInputDevice::Control(const char *name, void *cookie, status_t KeyboardInputDevice::HandleMonitor(BMessage *message) { - return B_OK; + int32 opcode = 0; + status_t status; + if ((status = message->FindInt32("opcode", &opcode)) < B_OK) + return status; + + if ((opcode != B_ENTRY_CREATED) + && (opcode != B_ENTRY_REMOVED)) + return B_OK; + + + BEntry entry; + BPath path; + dev_t device; + ino_t directory; + const char *name = NULL; + + message->FindInt32("device", &device); + message->FindInt64("directory", &directory); + message->FindString("name", &name); + + entry_ref ref(device, directory, name); + + if ((status = entry.SetTo(&ref)) != B_OK) + return status; + if ((status = entry.GetPath(&path)) != B_OK) + return status; + if ((status = path.InitCheck()) != B_OK) + return status; + + if (opcode == B_ENTRY_CREATED) + AddDevice(path.Path()); + else + RemoveDevice(path.Path()); + + return status; +} + + +status_t +KeyboardInputDevice::AddDevice(const char *path) +{ + keyboard_device *device = new keyboard_device(); + if (!device) + return B_NO_MEMORY; + + if ((device->fd = open(path, O_RDWR)) < B_OK) { + delete device; + return B_ERROR; + } + + device->fd = -1; + device->device_watcher = -1; + device->active = false; + strcpy(device->path, path); + device->device_ref.name = GetShortName(path); + device->device_ref.type = B_KEYBOARD_DEVICE; + device->device_ref.cookie = device; + device->owner = this; + + input_device_ref *devices[2]; + devices[0] = &device->device_ref; + devices[1] = NULL; + + fDevices.AddItem(device); + + InitFromSettings(device); + + return RegisterDevices(devices); +} + + +status_t +KeyboardInputDevice::RemoveDevice(const char *path) +{ + int32 i = 0; + keyboard_device *device = NULL; + while ((device = (keyboard_device *)fDevices.ItemAt(i)) != NULL) { + if (!strcmp(device->path, path)) { + free(device->device_ref.name); + if (device->fd >= 0) + close(device->fd); + fDevices.RemoveItem(device); + delete device; + return B_OK; + } + } + + return B_ENTRY_NOT_FOUND; } int32 KeyboardInputDevice::DeviceWatcher(void *arg) { - KeyboardInputDevice *dev = (KeyboardInputDevice *)arg; + keyboard_device *dev = (keyboard_device *)arg; return 0; } +char * +KeyboardInputDevice::GetShortName(const char *longName) +{ + BString string(longName); + BString name; + + int32 slash = string.FindLast("/"); + int32 previousSlash = string.FindLast("/", slash) + 1; + string.CopyInto(name, slash, string.Length() - slash); + + int32 deviceIndex = atoi(name.String()) + 1; + string.CopyInto(name, previousSlash, slash - previousSlash); + name << " Keyboard " << deviceIndex; + + return strdup(name.String()); +} + + +void +KeyboardInputDevice::RecursiveScan(const char *directory) +{ + BEntry entry; + BDirectory dir(directory); + while (dir.GetNextEntry(&entry) == B_OK) { + BPath path; + entry.GetPath(&path); + if (entry.IsDirectory()) + RecursiveScan(path.Path()); + else + AddDevice(path.Path()); + } +} diff --git a/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.h b/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.h index c1484fcabf..8329934871 100644 --- a/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.h +++ b/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.h @@ -28,12 +28,12 @@ #define __KEYBOARDINPUTDEVICE_H #include -#include +#include #include typedef struct { - bigtime_t key_repeat_delay; - int32 key_repeat_rate; + bigtime_t key_repeat_delay; + int32 key_repeat_rate; } kb_settings; class KeyboardInputDevice : public BInputServerDevice { @@ -50,16 +50,18 @@ public: uint32 command, BMessage *message); private: status_t HandleMonitor(BMessage *message); - status_t InitFromSettings(uint32 opcode = 0); - - thread_id fThread; - int fFd; - bool fQuit; - FILE *fLogFile; + status_t InitFromSettings(void *cookie, uint32 opcode = 0); + void RecursiveScan(const char *directory); + status_t AddDevice(const char *path); + status_t RemoveDevice(const char *path); + static int32 DeviceWatcher(void *arg); + static char *GetShortName(const char *longName); - kb_settings fSettings; + BList fDevices; + + static FILE *sLogFile; }; extern "C" BInputServerDevice *instantiate_input_device();