Przeglądaj źródła

device: linux: read joypad events in bulk

Daniele Bartolini 3 lat temu
rodzic
commit
af72fa35d1
1 zmienionych plików z 49 dodań i 44 usunięć
  1. 49 44
      src/device/main_linux.cpp

+ 49 - 44
src/device/main_linux.cpp

@@ -181,14 +181,14 @@ struct Joypad
 		s16 right[3];
 	};
 
+	DeviceEventQueue *_queue;
 	int _fd[CROWN_MAX_JOYPADS];
-	bool _connected[CROWN_MAX_JOYPADS];
 	AxisData _axis[CROWN_MAX_JOYPADS];
 
-	Joypad()
+	Joypad(DeviceEventQueue &queue)
+		: _queue(&queue)
 	{
 		memset(&_fd, 0, sizeof(_fd));
-		memset(&_connected, 0, sizeof(_connected));
 		memset(&_axis, 0, sizeof(_axis));
 	}
 
@@ -197,45 +197,28 @@ struct Joypad
 		char jspath[] = "/dev/input/jsX";
 		char *num = strchr(jspath, 'X');
 
-		for (u8 i = 0; i < CROWN_MAX_JOYPADS; ++i) {
-			*num = '0' + i;
-			_fd[i] = ::open(jspath, O_RDONLY);
+		for (u32 ii = 0; ii < CROWN_MAX_JOYPADS; ++ii) {
+			*num = '0' + ii;
+			_fd[ii] = ::open(jspath, O_RDONLY);
+			_queue->push_status_event(InputDeviceType::JOYPAD, ii, _fd[ii] >= 0);
 		}
-
-		memset(_connected, 0, sizeof(_connected));
-		memset(_axis, 0, sizeof(_axis));
 	}
 
 	void close()
 	{
-		for (u8 i = 0; i < CROWN_MAX_JOYPADS; ++i) {
-			if (_fd[i] != -1)
-				::close(_fd[i]);
+		for (u32 ii = 0; ii < CROWN_MAX_JOYPADS; ++ii) {
+			if (_fd[ii] != -1) {
+				::close(_fd[ii]);
+				_fd[ii] = -1;
+				_queue->push_status_event(InputDeviceType::JOYPAD, ii, false);
+			}
 		}
 	}
 
-	void update(DeviceEventQueue &queue, fd_set *fdset)
+	void process_events(u32 joypad_id, const JoypadEvent *events, u32 num_events)
 	{
-		JoypadEvent ev;
-		memset(&ev, 0, sizeof(ev));
-
-		for (u8 i = 0; i < CROWN_MAX_JOYPADS; ++i) {
-			const int fd = _fd[i];
-			const bool connected = fd != -1;
-
-			if (connected != _connected[i])
-				queue.push_status_event(InputDeviceType::JOYPAD, i, connected);
-
-			_connected[i] = connected;
-
-			if (!connected)
-				continue;
-
-			if (!FD_ISSET(fd, fdset))
-				continue;
-
-			read(fd, &ev, sizeof(ev));
-			s16 val = ev.value;
+		for (u32 ii = 0; ii < num_events; ++ii) {
+			JoypadEvent ev = events[ii];
 
 			switch (ev.type &= ~JS_EVENT_INIT) {
 			case JS_EVENT_AXIS: {
@@ -252,23 +235,24 @@ struct Joypad
 				};
 
 				// Remap triggers to [0, INT16_MAX]
+				s16 value = ev.value;
 				if (ev.number == 2 || ev.number == 5)
-					val = (val + INT16_MAX) >> 1;
+					value = (ev.value + INT16_MAX) >> 1;
 
-				s16 *values = ev.number > 2 ? _axis[i].right : _axis[i].left;
-				values[axis_idx[ev.number]] = val;
+				s16 *values = ev.number > 2 ? _axis[joypad_id].right : _axis[joypad_id].left;
+				values[axis_idx[ev.number]] = value;
 
 				if (ev.number == 2 || ev.number == 5) {
-					queue.push_axis_event(InputDeviceType::JOYPAD
-						, i
+					_queue->push_axis_event(InputDeviceType::JOYPAD
+						, joypad_id
 						, axis_map[ev.number]
 						, 0
 						, 0
 						, values[2]
 						);
 				} else if (ev.number < countof(axis_map)) {
-					queue.push_axis_event(InputDeviceType::JOYPAD
-						, i
+					_queue->push_axis_event(InputDeviceType::JOYPAD
+						, joypad_id
 						, axis_map[ev.number]
 						, values[0]
 						, -values[1]
@@ -280,10 +264,10 @@ struct Joypad
 
 			case JS_EVENT_BUTTON:
 				if (ev.number < countof(s_button)) {
-					queue.push_button_event(InputDeviceType::JOYPAD
-						, i
+					_queue->push_button_event(InputDeviceType::JOYPAD
+						, joypad_id
 						, s_button[ev.number]
-						, val == 1
+						, ev.value == 1
 						);
 				}
 				break;
@@ -293,6 +277,26 @@ struct Joypad
 			}
 		}
 	}
+
+	void update(fd_set *fdset)
+	{
+		for (u8 ii = 0; ii < CROWN_MAX_JOYPADS; ++ii) {
+			if (_fd[ii] == -1 || !FD_ISSET(_fd[ii], fdset))
+				continue;
+
+			// Read all events.
+			JoypadEvent events[64];
+			ssize_t num_bytes = read(_fd[ii], &events, sizeof(events));
+
+			if (num_bytes > 0) {
+				process_events(ii, events, num_bytes/ssize_t(sizeof(events[0])));
+			} else {
+				::close(_fd[ii]);
+				_fd[ii] = -1;
+				_queue->push_status_event(InputDeviceType::JOYPAD, ii, false);
+			}
+		}
+	}
 };
 
 static bool s_exit = false;
@@ -331,6 +335,7 @@ struct LinuxDevice
 		, _screen_config(NULL)
 		, _events(a)
 		, _queue(push_event)
+		, _joypad(_queue)
 		, _x11_window(None)
 		, _mouse_last_x(INT16_MAX)
 		, _mouse_last_y(INT16_MAX)
@@ -592,7 +597,7 @@ struct LinuxDevice
 					}
 				}
 			} else {
-				_joypad.update(_queue, &fdset);
+				_joypad.update(&fdset);
 			}
 		}