示例#1
0
JoypadLinux::~JoypadLinux() {
	exit_udev = true;
	Thread::wait_to_finish(joy_thread);
	memdelete(joy_thread);
	memdelete(joy_mutex);
	close_joypad();
}
示例#2
0
void JoypadLinux::monitor_joypads(udev *p_udev) {

	udev_device *dev = NULL;
	udev_monitor *mon = udev_monitor_new_from_netlink(p_udev, "udev");
	udev_monitor_filter_add_match_subsystem_devtype(mon, "input", NULL);
	udev_monitor_enable_receiving(mon);
	int fd = udev_monitor_get_fd(mon);

	while (!exit_udev) {

		fd_set fds;
		struct timeval tv;
		int ret;

		FD_ZERO(&fds);
		FD_SET(fd, &fds);
		tv.tv_sec = 0;
		tv.tv_usec = 0;

		ret = select(fd + 1, &fds, NULL, NULL, &tv);

		/* Check if our file descriptor has received data. */
		if (ret > 0 && FD_ISSET(fd, &fds)) {
			/* Make the call to receive the device.
			   select() ensured that this will not block. */
			dev = udev_monitor_receive_device(mon);

			if (dev && udev_device_get_devnode(dev) != 0) {

				joy_mutex->lock();
				String action = udev_device_get_action(dev);
				const char *devnode = udev_device_get_devnode(dev);
				if (devnode) {

					String devnode_str = devnode;
					if (devnode_str.find(ignore_str) == -1) {

						if (action == "add")
							open_joypad(devnode);
						else if (String(action) == "remove")
							close_joypad(get_joy_from_path(devnode));
					}
				}

				udev_device_unref(dev);
				joy_mutex->unlock();
			}
		}
		usleep(50000);
	}
	udev_monitor_unref(mon);
}
示例#3
0
文件: joypad.cpp 项目: zgub4/godot
void JoypadWindows::probe_joypads() {

	DWORD dwResult;
	for (DWORD i = 0; i < XUSER_MAX_COUNT; i++) {

		ZeroMemory(&x_joypads[i].state, sizeof(XINPUT_STATE));

		dwResult = xinput_get_state(i, &x_joypads[i].state);
		if (dwResult == ERROR_SUCCESS) {

			int id = input->get_unused_joy_id();
			if (id != -1 && !x_joypads[i].attached) {

				x_joypads[i].attached = true;
				x_joypads[i].id = id;
				x_joypads[i].ff_timestamp = 0;
				x_joypads[i].ff_end_timestamp = 0;
				x_joypads[i].vibrating = false;
				attached_joypads[id] = true;
				input->joy_connection_changed(id, true, "XInput Gamepad", "__XINPUT_DEVICE__");
			}
		} else if (x_joypads[i].attached) {

			x_joypads[i].attached = false;
			attached_joypads[x_joypads[i].id] = false;
			input->joy_connection_changed(x_joypads[i].id, false, "");
		}
	}

	for (int i = 0; i < joypad_count; i++) {

		d_joypads[i].confirmed = false;
	}

	dinput->EnumDevices(DI8DEVCLASS_GAMECTRL, enumCallback, this, DIEDFL_ATTACHEDONLY);

	for (int i = 0; i < joypad_count; i++) {

		if (!d_joypads[i].confirmed) {

			close_joypad(i);
		}
	}
}
示例#4
0
void JoypadLinux::close_joypad(int p_id) {
	if (p_id == -1) {
		for (int i = 0; i < JOYPADS_MAX; i++) {

			close_joypad(i);
		};
		return;
	} else if (p_id < 0)
		return;

	Joypad &joy = joypads[p_id];

	if (joy.fd != -1) {

		close(joy.fd);
		joy.fd = -1;
		attached_devices.remove(attached_devices.find(joy.devpath));
		input->joy_connection_changed(p_id, false, "");
	};
}
示例#5
0
文件: joypad.cpp 项目: zgub4/godot
void JoypadWindows::close_joypad(int id) {

	if (id == -1) {

		for (int i = 0; i < JOYPADS_MAX; i++) {

			close_joypad(i);
		}
		return;
	}

	if (!d_joypads[id].attached) return;

	d_joypads[id].di_joy->Unacquire();
	d_joypads[id].di_joy->Release();
	d_joypads[id].attached = false;
	attached_joypads[d_joypads[id].id] = false;
	d_joypads[id].guid.Data1 = d_joypads[id].guid.Data2 = d_joypads[id].guid.Data3 = 0;
	input->joy_connection_changed(d_joypads[id].id, false, "");
	joypad_count--;
}
示例#6
0
void JoypadLinux::process_joypads() {

	if (joy_mutex->try_lock() != OK) {
		return;
	}
	for (int i = 0; i < JOYPADS_MAX; i++) {

		if (joypads[i].fd == -1) continue;

		input_event events[32];
		Joypad *joy = &joypads[i];

		int len;

		while ((len = read(joy->fd, events, (sizeof events))) > 0) {
			len /= sizeof(events[0]);
			for (int j = 0; j < len; j++) {

				input_event &ev = events[j];

				// ev may be tainted and out of MAX_KEY range, which will cause
				// joy->key_map[ev.code] to crash
				if (ev.code < 0 || ev.code >= MAX_KEY)
					return;

				switch (ev.type) {
					case EV_KEY:
						input->joy_button(i, joy->key_map[ev.code], ev.value);
						break;

					case EV_ABS:

						switch (ev.code) {
							case ABS_HAT0X:
								if (ev.value != 0) {
									if (ev.value < 0)
										joy->dpad |= InputDefault::HAT_MASK_LEFT;
									else
										joy->dpad |= InputDefault::HAT_MASK_RIGHT;
								} else
									joy->dpad &= ~(InputDefault::HAT_MASK_LEFT | InputDefault::HAT_MASK_RIGHT);

								input->joy_hat(i, joy->dpad);
								break;

							case ABS_HAT0Y:
								if (ev.value != 0) {
									if (ev.value < 0)
										joy->dpad |= InputDefault::HAT_MASK_UP;
									else
										joy->dpad |= InputDefault::HAT_MASK_DOWN;
								} else
									joy->dpad &= ~(InputDefault::HAT_MASK_UP | InputDefault::HAT_MASK_DOWN);

								input->joy_hat(i, joy->dpad);
								break;

							default:
								if (joy->abs_map[ev.code] != -1 && joy->abs_info[ev.code]) {
									InputDefault::JoyAxis value = axis_correct(joy->abs_info[ev.code], ev.value);
									joy->curr_axis[joy->abs_map[ev.code]] = value;
								}
								break;
						}
						break;
				}
			}
		}
		for (int j = 0; j < MAX_ABS; j++) {
			int index = joy->abs_map[j];
			if (index != -1) {
				input->joy_axis(i, index, joy->curr_axis[index]);
			}
		}
		if (len == 0 || (len < 0 && errno != EAGAIN)) {
			close_joypad(i);
		};

		if (joy->force_feedback) {
			uint64_t timestamp = input->get_joy_vibration_timestamp(i);
			if (timestamp > joy->ff_effect_timestamp) {
				Vector2 strength = input->get_joy_vibration_strength(i);
				float duration = input->get_joy_vibration_duration(i);
				if (strength.x == 0 && strength.y == 0) {
					joypad_vibration_stop(i, timestamp);
				} else {
					joypad_vibration_start(i, strength.x, strength.y, duration, timestamp);
				}
			}
		}
	}
	joy_mutex->unlock();
}
示例#7
0
文件: joypad.cpp 项目: zgub4/godot
JoypadWindows::~JoypadWindows() {

	close_joypad();
	dinput->Release();
	unload_xinput();
}