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;
}
Beispiel #2
0
status_t
TabletProtocolHandler::_ReadReport(void *buffer)
{
	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_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_INTERRUPTED;
	}

	float axisAbsoluteData[2];
	axisAbsoluteData[0] = 0.0f;
	axisAbsoluteData[1] = 0.0f;

	if (fXAxis.Extract() == B_OK && fXAxis.Valid())
		axisAbsoluteData[0] = fXAxis.ScaledFloatData();

	if (fYAxis.Extract() == B_OK && fYAxis.Valid())
		axisAbsoluteData[1] = fYAxis.ScaledFloatData();

	uint32 wheelData = 0;
	if (fWheel != NULL && fWheel->Extract() == B_OK && fWheel->Valid())
		wheelData = fWheel->Data();

	uint32 buttons = 0;
	for (uint32 i = 0; i < B_MAX_MOUSE_BUTTONS; i++) {
		HIDReportItem *button = fButtons[i];
		if (button == NULL)
			break;

		if (button->Extract() == B_OK && button->Valid())
			buttons |= (button->Data() & 1) << (button->UsageID() - 1);
	}

	float pressure = 1.0f;
	if (fPressure != NULL && fPressure->Extract() == B_OK
		&& fPressure->Valid()) {
		pressure = fPressure->ScaledFloatData();
	}

	float xTilt = 0.0f;
	if (fXTilt != NULL && fXTilt->Extract() == B_OK && fXTilt->Valid())
		xTilt = fXTilt->ScaledFloatData();

	float yTilt = 0.0f;
	if (fXTilt != NULL && fYTilt->Extract() == B_OK && fYTilt->Valid())
		yTilt = fYTilt->ScaledFloatData();

	bool inRange = true;
	if (fRange != NULL)
		inRange = fRange->Extract() == B_OK && fRange->Valid();

	bool eraser = false;
	if (fEraser != NULL && fEraser->Extract() == B_OK && fEraser->Valid())
		eraser = (fEraser->Data() & 1) != 0;

	fReport.DoneProcessing();
	TRACE("got tablet report\n");

	int32 clicks = 0;
	bigtime_t timestamp = system_time();
	if (buttons != 0) {
		if (fLastButtons == 0) {
			if (fLastClickTime + fClickSpeed > timestamp)
				fClickCount++;
			else
				fClickCount = 1;
		}

		fLastClickTime = timestamp;
		clicks = fClickCount;
	}

	fLastButtons = buttons;

	tablet_movement *info = (tablet_movement *)buffer;
	memset(info, 0, sizeof(tablet_movement));

	info->xpos = axisAbsoluteData[0];
	info->ypos = axisAbsoluteData[1];
	info->has_contact = inRange;
	info->pressure = pressure;
	info->eraser = eraser;
	info->tilt_x = xTilt;
	info->tilt_y = yTilt;

	info->buttons = buttons;
	info->clicks = clicks;
	info->timestamp = timestamp;
	info->wheel_ydelta = -wheelData;

	return B_OK;
}