blob: 7a493a74eda3ff9561cae9ff1f838e27053c2f5c (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
#include "impl/input-device-serial-controller.hh"
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
namespace nes::app::mac
{
input_device_serial_controller::input_device_serial_controller(char const* path)
: path_{ path }
{
fd_ = open(path, O_RDONLY | O_NOCTTY | O_NDELAY | O_NONBLOCK);
if (fd_ == -1)
{
perror("input_device_serial_controller: open");
return;
}
if (!set_up()) { close(); }
}
input_device_serial_controller::~input_device_serial_controller()
{
close();
}
auto input_device_serial_controller::is_reliable() const -> bool
{
return fd_ != -1;
}
auto input_device_serial_controller::read_buttons() -> sys::button_mask
{
if (fd_ == -1) { return sys::button_mask{}; }
// Poll for any updates until we can't read anymore.
while (true)
{
auto buf = u8{};
auto const res = read(fd_, &buf, 1);
if (res == -1)
{
if (errno == EAGAIN || errno == EWOULDBLOCK) { break; }
perror("read from controller");
close();
break;
}
current_ = sys::button_mask::from_raw_value(buf);
}
return current_;
}
auto input_device_serial_controller::set_up() -> bool
{
if (ioctl(fd_, TIOCEXCL) == -1)
{
perror("input_device_serial_controller: ioctl");
return false;
}
auto attr = termios{};
if (tcgetattr(fd_, &attr) == -1)
{
perror("input_device_serial_controller: tcgetattr");
return false;
}
cfsetispeed(&attr, B57600);
cfsetospeed(&attr, B57600);
attr.c_cflag = attr.c_cflag | CLOCAL | CREAD;
attr.c_cflag = (attr.c_cflag & static_cast<tcflag_t>(~CSIZE)) | CS8;
if (tcsetattr(fd_, TCSANOW, &attr) == -1)
{
perror("input_device_serial_controller: tcsetattr");
return false;
}
return true;
}
auto input_device_serial_controller::close() -> void
{
if (fd_ != -1)
{
::close(fd_);
fd_ = -1;
}
}
} // namespace nes::app::mac
|