status_t JoystickProtocolHandler::_Update() { status_t result = fReport.WaitForReport(B_INFINITE_TIMEOUT); if (result != B_OK) { if (fReport.Device()->IsRemoved()) { TRACE("device has been removed\n"); return B_DEV_NOT_READY; } if (result == B_CANCELED) return B_CANCELED; if (result != B_INTERRUPTED) { // interrupts happen when other reports come in on the same // input as ours TRACE_ALWAYS("error waiting for report: %s\n", strerror(result)); } // signal that we simply want to try again return B_OK; } result = mutex_lock(&fUpdateLock); if (result != B_OK) { fReport.DoneProcessing(); return result; } memset(fCurrentValues.data, 0, fCurrentValues.data_size); for (uint32 i = 0; i < fAxisCount; i++) { if (fAxis[i] == NULL) continue; if (fAxis[i]->Extract() == B_OK && fAxis[i]->Valid()) fCurrentValues.axes[i] = (int16)fAxis[i]->ScaledData(16, true); } for (uint32 i = 0; i < fHatCount; i++) { HIDReportItem *hat = fHats[i]; if (hat == NULL) continue; if (hat->Extract() != B_OK || !hat->Valid()) continue; fCurrentValues.hats[i] = hat->ScaledRangeData(1, 8); } for (uint32 i = 0; i < fButtonCount; i++) { HIDReportItem *button = fButtons[i]; if (button == NULL) break; uint16 index = button->UsageID() - 1; if (index >= fMaxButton) continue; if (button->Extract() == B_OK && button->Valid()) { fCurrentValues.buttons[index / 32] |= (button->Data() & 1) << (index % 32); } } fReport.DoneProcessing(); TRACE("got joystick report\n"); *fCurrentValues.timestamp = system_time(); mutex_unlock(&fUpdateLock); return B_OK; }