diff --git a/src/add-ons/kernel/drivers/input/usb_hid/JoystickProtocolHandler.cpp b/src/add-ons/kernel/drivers/input/usb_hid/JoystickProtocolHandler.cpp index 4917f1f1ce..58902de092 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/JoystickProtocolHandler.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/JoystickProtocolHandler.cpp @@ -22,9 +22,13 @@ JoystickProtocolHandler::JoystickProtocolHandler(HIDReport &report) : - ProtocolHandler(report.Device(), "joystick/usb/", 512), - fReport(report) + ProtocolHandler(report.Device(), "joystick/usb/", 0), + fReport(report), + fUpdateThread(-1) { + mutex_init(&fUpdateLock, "joystick update lock"); + memset(&fCurrentValues, 0, sizeof(extended_joystick)); + for (uint32 i = 0; i < MAX_AXES; i++) fAxis[i] = NULL; @@ -129,6 +133,45 @@ JoystickProtocolHandler::AddHandlers(HIDDevice &device, } +status_t +JoystickProtocolHandler::Open(uint32 flags, uint32 *cookie) +{ + status_t result = mutex_lock(&fUpdateLock); + if (result != B_OK) + return result; + + if (fUpdateThread < 0) { + fUpdateThread = spawn_kernel_thread(_UpdateThread, "joystick update", + B_NORMAL_PRIORITY, (void *)this); + + if (fUpdateThread < 0) + result = fUpdateThread; + else + resume_thread(fUpdateThread); + } + + mutex_unlock(&fUpdateLock); + if (result != B_OK) + return result; + + return ProtocolHandler::Open(flags, cookie); +} + + +status_t +JoystickProtocolHandler::Close(uint32 *cookie) +{ + status_t result = mutex_lock(&fUpdateLock); + if (result == B_OK) { + fUpdateThread = -1; + mutex_unlock(&fUpdateLock); + } + + return ProtocolHandler::Close(cookie); +} + + + status_t JoystickProtocolHandler::Read(uint32 *cookie, off_t position, void *buffer, size_t *numBytes) @@ -136,15 +179,15 @@ JoystickProtocolHandler::Read(uint32 *cookie, off_t position, void *buffer, if (*numBytes < sizeof(extended_joystick)) return B_BUFFER_OVERFLOW; - while (RingBufferReadable() == 0) { - status_t result = _ReadReport(); - if (result != B_OK) - return result; + // this is a polling interface, we just return the current value + status_t result = mutex_lock(&fUpdateLock); + if (result != B_OK) { + *numBytes = 0; + return result; } - status_t result = RingBufferRead(buffer, sizeof(extended_joystick)); - if (result != B_OK) - return result; + memcpy(buffer, &fCurrentValues, sizeof(extended_joystick)); + mutex_unlock(&fUpdateLock); *numBytes = sizeof(extended_joystick); return B_OK; @@ -206,8 +249,22 @@ JoystickProtocolHandler::Control(uint32 *cookie, uint32 op, void *buffer, } +int32 +JoystickProtocolHandler::_UpdateThread(void *data) +{ + JoystickProtocolHandler *handler = (JoystickProtocolHandler *)data; + while (handler->fUpdateThread == find_thread(NULL)) { + status_t result = handler->_Update(); + if (result != B_OK) + return result; + } + + return B_OK; +} + + status_t -JoystickProtocolHandler::_ReadReport() +JoystickProtocolHandler::_Update() { status_t result = fReport.WaitForReport(B_INFINITE_TIMEOUT); if (result != B_OK) { @@ -226,15 +283,20 @@ JoystickProtocolHandler::_ReadReport() return B_OK; } - extended_joystick info; - memset(&info, 0, sizeof(info)); + result = mutex_lock(&fUpdateLock); + if (result != B_OK) { + fReport.DoneProcessing(); + return result; + } + + memset(&fCurrentValues, 0, sizeof(extended_joystick)); for (uint32 i = 0; i < MAX_AXES; i++) { if (fAxis[i] == NULL) continue; if (fAxis[i]->Extract() == B_OK && fAxis[i]->Valid()) - info.axes[i] = (int16)fAxis[i]->ScaledData(16, true); + fCurrentValues.axes[i] = (int16)fAxis[i]->ScaledData(16, true); } for (uint32 i = 0; i < MAX_BUTTONS; i++) { @@ -242,13 +304,16 @@ JoystickProtocolHandler::_ReadReport() if (button == NULL) break; - if (button->Extract() == B_OK && button->Valid()) - info.buttons |= (button->Data() & 1) << (button->UsageID() - 1); + if (button->Extract() == B_OK && button->Valid()) { + fCurrentValues.buttons + |= (button->Data() & 1) << (button->UsageID() - 1); + } } fReport.DoneProcessing(); TRACE("got joystick report\n"); - info.timestamp = system_time(); - return RingBufferWrite(&info, sizeof(info)); + fCurrentValues.timestamp = system_time(); + mutex_unlock(&fUpdateLock); + return B_OK; } diff --git a/src/add-ons/kernel/drivers/input/usb_hid/JoystickProtocolHandler.h b/src/add-ons/kernel/drivers/input/usb_hid/JoystickProtocolHandler.h index 470f221f2e..6257a7654c 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/JoystickProtocolHandler.h +++ b/src/add-ons/kernel/drivers/input/usb_hid/JoystickProtocolHandler.h @@ -11,6 +11,7 @@ #include "ProtocolHandler.h" #include +#include class HIDCollection; @@ -25,6 +26,9 @@ public: HIDCollection &collection, ProtocolHandler *&handlerList); + virtual status_t Open(uint32 flags, uint32 *cookie); + virtual status_t Close(uint32 *cookie); + virtual status_t Read(uint32 *cookie, off_t position, void *buffer, size_t *numBytes); virtual status_t Write(uint32 *cookie, off_t position, @@ -34,15 +38,19 @@ public: void *buffer, size_t length); private: - status_t _ReadReport(); + static int32 _UpdateThread(void *data); + status_t _Update(); -private: HIDReport & fReport; HIDReportItem * fAxis[MAX_AXES]; HIDReportItem * fButtons[MAX_BUTTONS]; joystick_module_info fJoystickModuleInfo; + + extended_joystick fCurrentValues; + mutex fUpdateLock; + thread_id fUpdateThread; }; #endif // USB_JOYSTICK_PROTOCOL_HANDLER_H