procon_bypass_man 0.1.8 → 0.1.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +3 -2
- data/.github/workflows/ruby.yml +5 -4
- data/.gitignore +5 -0
- data/.rubocop.yml +2 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +18 -1
- data/Gemfile +4 -0
- data/Gemfile.lock +53 -2
- data/README.md +14 -8
- data/Steepfile +39 -0
- data/bin/console +4 -0
- data/bin/dev_api_server.rb +18 -0
- data/docs/setup_raspi.mitamae.rb +12 -0
- data/lib/procon_bypass_man/background/has_server_pool.rb +54 -0
- data/lib/procon_bypass_man/background/http_client.rb +70 -0
- data/lib/procon_bypass_man/background/job_performer.rb +16 -0
- data/lib/procon_bypass_man/background/job_runnable.rb +16 -0
- data/lib/procon_bypass_man/background/job_runner.rb +44 -0
- data/lib/procon_bypass_man/background/jobs/base_job.rb +12 -0
- data/lib/procon_bypass_man/background/jobs/report_boot_job.rb +10 -0
- data/lib/procon_bypass_man/background/jobs/report_error_job.rb +10 -0
- data/lib/procon_bypass_man/background/jobs/report_heartbeat_job.rb +10 -0
- data/lib/procon_bypass_man/background/jobs/report_pressed_buttons_job.rb +18 -0
- data/lib/procon_bypass_man/background/jobs/report_reload_config_job.rb +10 -0
- data/lib/procon_bypass_man/background.rb +10 -0
- data/lib/procon_bypass_man/boot_message.rb +42 -0
- data/lib/procon_bypass_man/{configuration → buttons_setting_configuration}/layer.rb +50 -4
- data/lib/procon_bypass_man/{configuration → buttons_setting_configuration}/loader.rb +12 -11
- data/lib/procon_bypass_man/{configuration → buttons_setting_configuration}/validator.rb +1 -1
- data/lib/procon_bypass_man/buttons_setting_configuration.rb +101 -0
- data/lib/procon_bypass_man/bypass/usb_hid_logger.rb +36 -0
- data/lib/procon_bypass_man/bypass.rb +61 -29
- data/lib/procon_bypass_man/callbacks.rb +70 -0
- data/lib/procon_bypass_man/commands/connect_device_command.rb +11 -0
- data/lib/procon_bypass_man/commands/print_boot_message_command.rb +9 -0
- data/lib/procon_bypass_man/commands/send_error_command.rb +18 -0
- data/lib/procon_bypass_man/commands/send_reload_config_event_command.rb +10 -0
- data/lib/procon_bypass_man/commands/write_device_id_command.rb +11 -0
- data/lib/procon_bypass_man/commands/write_session_id_command.rb +13 -0
- data/lib/procon_bypass_man/commands.rb +6 -0
- data/lib/procon_bypass_man/configuration.rb +92 -67
- data/lib/procon_bypass_man/device_connector.rb +11 -29
- data/lib/procon_bypass_man/io_monitor.rb +16 -8
- data/lib/procon_bypass_man/on_memory_cache.rb +34 -0
- data/lib/procon_bypass_man/procon/analog_stick.rb +31 -0
- data/lib/procon_bypass_man/procon/analog_stick_cap.rb +65 -0
- data/lib/procon_bypass_man/procon/button_collection.rb +15 -6
- data/lib/procon_bypass_man/procon/{data.rb → consts.rb} +1 -1
- data/lib/procon_bypass_man/procon/layer_changer.rb +40 -0
- data/lib/procon_bypass_man/procon/macro_registry.rb +2 -2
- data/lib/procon_bypass_man/procon/mode_registry.rb +4 -4
- data/lib/procon_bypass_man/procon/press_button_aware.rb +13 -0
- data/lib/procon_bypass_man/procon/user_operation.rb +21 -16
- data/lib/procon_bypass_man/procon.rb +23 -9
- data/lib/procon_bypass_man/procon_reader.rb +31 -0
- data/lib/procon_bypass_man/runner.rb +43 -64
- data/lib/procon_bypass_man/uptime.rb +14 -2
- data/lib/procon_bypass_man/version.rb +1 -1
- data/lib/procon_bypass_man.rb +38 -43
- data/project_template/README.md +1 -1
- data/project_template/app.rb +7 -5
- data/project_template/systemd_units/pbm_web.service +11 -0
- data/project_template/web.rb +16 -0
- data/sig/README.rb +4 -0
- data/sig/main.rbs +505 -0
- metadata +42 -11
- data/examples/practical/app.rb +0 -21
- data/examples/practical/setting.yml +0 -24
- data/lib/procon_bypass_man/procon/layer_changeable.rb +0 -28
- data/lib/procon_bypass_man/procon/pressed_button_helper.rb +0 -25
@@ -1,86 +1,111 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
module ProconBypassMan
|
6
|
-
class Configuration
|
7
|
-
|
8
|
-
attr_accessor :layers,
|
9
|
-
:setting_path,
|
10
|
-
:mode_plugins,
|
11
|
-
:macro_plugins,
|
12
|
-
:context,
|
13
|
-
:current_context_key
|
14
|
-
|
15
|
-
def self.instance
|
16
|
-
@@current_context_key ||= :main
|
17
|
-
@@context ||= {}
|
18
|
-
@@context[@@current_context_key] ||= new
|
1
|
+
class ProconBypassMan::Configuration
|
2
|
+
module ClassMethods
|
3
|
+
def root
|
4
|
+
config.root
|
19
5
|
end
|
20
6
|
|
21
|
-
def
|
22
|
-
|
23
|
-
previous_key = @@current_context_key
|
24
|
-
if block_given?
|
25
|
-
@@current_context_key = key
|
26
|
-
value = yield(@@context[key])
|
27
|
-
@@current_context_key = previous_key
|
28
|
-
return value
|
29
|
-
else
|
30
|
-
@@current_context_key = key
|
31
|
-
end
|
7
|
+
def logger
|
8
|
+
config.logger
|
32
9
|
end
|
33
10
|
|
34
|
-
def
|
35
|
-
|
11
|
+
def error_logger
|
12
|
+
config.error_logger
|
36
13
|
end
|
37
14
|
|
38
|
-
|
39
|
-
|
40
|
-
if mode.respond_to?(:name)
|
41
|
-
mode_name = mode.name.to_sym
|
42
|
-
else
|
43
|
-
mode_name = mode
|
44
|
-
end
|
45
|
-
unless (MODES + ProconBypassMan::Procon::ModeRegistry.plugins.keys).include?(mode_name)
|
46
|
-
raise("#{mode_name} mode is unknown")
|
47
|
-
end
|
48
|
-
|
49
|
-
layer = Layer.new(mode: mode_name)
|
50
|
-
layer.instance_eval(&block) if block_given?
|
51
|
-
self.layers[direction] = layer
|
52
|
-
self
|
15
|
+
def pid_path
|
16
|
+
@@pid_path ||= File.expand_path("#{root}/pbm_pid", __dir__).freeze
|
53
17
|
end
|
54
18
|
|
55
|
-
def
|
56
|
-
|
57
|
-
self
|
19
|
+
def digest_path
|
20
|
+
config.digest_path
|
58
21
|
end
|
59
22
|
|
60
|
-
def
|
61
|
-
ProconBypassMan::
|
62
|
-
self
|
23
|
+
def cache
|
24
|
+
@@cache_table ||= ProconBypassMan::OnMemoryCache.new
|
63
25
|
end
|
64
26
|
|
65
|
-
|
66
|
-
|
67
|
-
|
27
|
+
# @return [String]
|
28
|
+
def session_id
|
29
|
+
ProconBypassMan::WriteSessionIdCommand.execute
|
68
30
|
end
|
69
31
|
|
70
|
-
|
71
|
-
|
32
|
+
# @return [String]
|
33
|
+
def device_id
|
34
|
+
ProconBypassMan::WriteDeviceIdCommand.execute
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_accessor :enable_critical_error_logging, :raw_setting
|
39
|
+
attr_writer :verbose_bypass_log
|
40
|
+
|
41
|
+
def root=(path)
|
42
|
+
@root = path
|
43
|
+
return self
|
44
|
+
end
|
45
|
+
|
46
|
+
def root
|
47
|
+
if defined?(@root)
|
48
|
+
@root
|
49
|
+
else
|
50
|
+
File.expand_path('..', __dir__ || ".").freeze
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def api_servers=(api_servers)
|
55
|
+
@api_servers = api_servers
|
56
|
+
return self
|
57
|
+
end
|
58
|
+
|
59
|
+
def logger=(logger)
|
60
|
+
@logger = logger
|
61
|
+
return self
|
62
|
+
end
|
63
|
+
|
64
|
+
def logger
|
65
|
+
if ENV["PBM_ENV"] == 'test'
|
66
|
+
return Logger.new($stdout)
|
72
67
|
end
|
73
68
|
|
74
|
-
|
75
|
-
@
|
76
|
-
|
77
|
-
|
78
|
-
self.layers = {
|
79
|
-
up: Layer.new,
|
80
|
-
down: Layer.new,
|
81
|
-
left: Layer.new,
|
82
|
-
right: Layer.new,
|
83
|
-
}
|
69
|
+
if defined?(@logger) && @logger.is_a?(Logger)
|
70
|
+
@logger
|
71
|
+
else
|
72
|
+
Logger.new(File.open("/dev/null"))
|
84
73
|
end
|
85
74
|
end
|
75
|
+
|
76
|
+
def error_logger
|
77
|
+
if enable_critical_error_logging
|
78
|
+
@@error_logger ||= Logger.new("#{ProconBypassMan.root}/error.log", 5, 1024 * 1024 * 10)
|
79
|
+
else
|
80
|
+
Logger.new(File.open("/dev/null"))
|
81
|
+
end
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
def digest_path
|
86
|
+
"#{root}/.setting_yaml_digest"
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [String] pbm-webの接続先
|
90
|
+
def internal_api_servers
|
91
|
+
if !!ENV["INTERNAL_API_SERVER"]
|
92
|
+
[ENV["INTERNAL_API_SERVER"]]
|
93
|
+
else
|
94
|
+
[ 'http://localhost:9090',
|
95
|
+
'http://localhost:8080',
|
96
|
+
].compact
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def api_servers
|
101
|
+
if !!ENV["API_SERVER"]
|
102
|
+
[ENV["API_SERVER"]].reject(&:nil?)
|
103
|
+
else
|
104
|
+
[@api_servers].flatten.reject(&:nil?)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def verbose_bypass_log
|
109
|
+
@verbose_bypass_log || !!ENV["VERBOSE_BYPASS_LOG"]
|
110
|
+
end
|
86
111
|
end
|
@@ -12,23 +12,6 @@ class ProconBypassMan::DeviceConnector
|
|
12
12
|
PROCON_PATH = "/dev/hidraw0"
|
13
13
|
PROCON2_PATH = "/dev/hidraw1"
|
14
14
|
|
15
|
-
# 画面で再接続ができたが状況は変わらない
|
16
|
-
def self.reset_connection!
|
17
|
-
s = new
|
18
|
-
s.add([
|
19
|
-
["0000"],
|
20
|
-
["0000"],
|
21
|
-
["8005"],
|
22
|
-
["0000"],
|
23
|
-
["8001"],
|
24
|
-
], read_from: :switch)
|
25
|
-
s.drain_all
|
26
|
-
s.read_procon
|
27
|
-
s.write_switch("213c910080005db7723d48720a800300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
|
28
|
-
sleep(10) # いらないかも
|
29
|
-
s
|
30
|
-
end
|
31
|
-
|
32
15
|
def self.connect
|
33
16
|
s = new(throw_error_if_timeout: true, enable_at_exit: false)
|
34
17
|
s.add([
|
@@ -75,7 +58,7 @@ class ProconBypassMan::DeviceConnector
|
|
75
58
|
timer = ProconBypassMan::Timer.new
|
76
59
|
begin
|
77
60
|
timer.throw_if_timeout!
|
78
|
-
data = from_device(item).read_nonblock(
|
61
|
+
data = from_device(item).read_nonblock(64)
|
79
62
|
rescue IO::EAGAINWaitReadable
|
80
63
|
retry
|
81
64
|
end
|
@@ -128,7 +111,7 @@ class ProconBypassMan::DeviceConnector
|
|
128
111
|
timer = ProconBypassMan::Timer.new
|
129
112
|
begin
|
130
113
|
timer.throw_if_timeout!
|
131
|
-
data = switch.read_nonblock(
|
114
|
+
data = switch.read_nonblock(64)
|
132
115
|
ProconBypassMan.logger.debug { " >>> #{data.unpack("H*")})" }
|
133
116
|
rescue IO::EAGAINWaitReadable
|
134
117
|
retry
|
@@ -163,7 +146,7 @@ class ProconBypassMan::DeviceConnector
|
|
163
146
|
timer = ProconBypassMan::Timer.new
|
164
147
|
begin
|
165
148
|
timer.throw_if_timeout!
|
166
|
-
data = procon.read_nonblock(
|
149
|
+
data = procon.read_nonblock(64)
|
167
150
|
ProconBypassMan.logger.error " <<< #{data.unpack("H*")})"
|
168
151
|
rescue IO::EAGAINWaitReadable
|
169
152
|
retry
|
@@ -184,7 +167,7 @@ class ProconBypassMan::DeviceConnector
|
|
184
167
|
timer = ProconBypassMan::Timer.new
|
185
168
|
begin
|
186
169
|
timer.throw_if_timeout!
|
187
|
-
data = procon.read_nonblock(
|
170
|
+
data = procon.read_nonblock(64)
|
188
171
|
ProconBypassMan.logger.debug { " <<< #{data.unpack("H*")})" }
|
189
172
|
rescue IO::EAGAINWaitReadable
|
190
173
|
retry
|
@@ -217,7 +200,7 @@ class ProconBypassMan::DeviceConnector
|
|
217
200
|
timer = ProconBypassMan::Timer.new
|
218
201
|
begin
|
219
202
|
timer.throw_if_timeout!
|
220
|
-
data = switch.read_nonblock(
|
203
|
+
data = switch.read_nonblock(64)
|
221
204
|
ProconBypassMan.logger.debug { " >>> #{data.unpack("H*")})" }
|
222
205
|
rescue IO::EAGAINWaitReadable
|
223
206
|
retry
|
@@ -281,7 +264,7 @@ class ProconBypassMan::DeviceConnector
|
|
281
264
|
|
282
265
|
file = File.open(path, "w+")
|
283
266
|
begin
|
284
|
-
file.read_nonblock(
|
267
|
+
file.read_nonblock(64)
|
285
268
|
rescue EOFError
|
286
269
|
file.close
|
287
270
|
return false
|
@@ -303,12 +286,12 @@ class ProconBypassMan::DeviceConnector
|
|
303
286
|
case
|
304
287
|
when is_available_device?(PROCON_PATH)
|
305
288
|
ProconBypassMan.logger.info "proconのデバイスファイルは#{PROCON_PATH}を使います"
|
306
|
-
@procon = File.open(PROCON_PATH, "w+")
|
307
|
-
@gadget = File.open('/dev/hidg0', "w+")
|
289
|
+
@procon = File.open(PROCON_PATH, "w+b")
|
290
|
+
@gadget = File.open('/dev/hidg0', "w+b")
|
308
291
|
when is_available_device?(PROCON2_PATH)
|
309
292
|
ProconBypassMan.logger.info "proconのデバイスファイルは#{PROCON2_PATH}を使います"
|
310
|
-
@procon = File.open(PROCON2_PATH, "w+")
|
311
|
-
@gadget = File.open('/dev/hidg0', "w+")
|
293
|
+
@procon = File.open(PROCON2_PATH, "w+b")
|
294
|
+
@gadget = File.open('/dev/hidg0', "w+b")
|
312
295
|
else
|
313
296
|
raise "/dev/hidraw0, /dev/hidraw1の両方見つかりませんでした"
|
314
297
|
end
|
@@ -326,8 +309,7 @@ class ProconBypassMan::DeviceConnector
|
|
326
309
|
end
|
327
310
|
rescue Errno::ENXIO => e
|
328
311
|
# /dev/hidg0 をopenできないときがある
|
329
|
-
ProconBypassMan.
|
330
|
-
ProconBypassMan.logger.error e
|
312
|
+
ProconBypassMan::SendErrorCommand.execute(error: "Errno::ENXIO (No such device or address @ rb_sysopen - /dev/hidg0)が起きました。resetします. #{e.full_message}")
|
331
313
|
system('echo > /sys/kernel/config/usb_gadget/procon/UDC')
|
332
314
|
system('ls /sys/class/udc > /sys/kernel/config/usb_gadget/procon/UDC')
|
333
315
|
sleep 2
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module ProconBypassMan
|
2
2
|
class Counter
|
3
|
-
attr_accessor :label, :table, :previous_table
|
3
|
+
attr_accessor :label, :table, :previous_table, :active
|
4
4
|
|
5
5
|
def initialize(label: )
|
6
6
|
self.label = label
|
7
7
|
self.table = {}
|
8
8
|
self.previous_table = {}
|
9
|
+
self.active = true
|
9
10
|
end
|
10
11
|
|
11
12
|
# アクティブなバケットは1つだけ
|
@@ -24,7 +25,7 @@ module ProconBypassMan
|
|
24
25
|
self
|
25
26
|
end
|
26
27
|
|
27
|
-
def
|
28
|
+
def formatted_previous_table
|
28
29
|
t = previous_table.dup
|
29
30
|
start_function = t[:start_function] || 0
|
30
31
|
end_function = t[:end_function] || 0
|
@@ -32,6 +33,10 @@ module ProconBypassMan
|
|
32
33
|
eagain_wait_readable_on_write = t[:eagain_wait_readable_on_write] || 0
|
33
34
|
"(#{(end_function / start_function.to_f * 100).floor(1)}%(#{end_function}/#{start_function}), loss: #{eagain_wait_readable_on_read}, #{eagain_wait_readable_on_write})"
|
34
35
|
end
|
36
|
+
|
37
|
+
def shutdown
|
38
|
+
self.active = false
|
39
|
+
end
|
35
40
|
end
|
36
41
|
|
37
42
|
module IOMonitor
|
@@ -51,21 +56,24 @@ module ProconBypassMan
|
|
51
56
|
Thread.start do
|
52
57
|
max_output_length = 0
|
53
58
|
loop do
|
54
|
-
list = @@list.dup
|
59
|
+
list = @@list.select(&:active).dup
|
55
60
|
unless list.all? { |x| x&.previous_table.is_a?(Hash) }
|
56
61
|
sleep 0.5
|
57
62
|
next
|
58
63
|
end
|
59
64
|
|
60
65
|
line = list.map { |counter|
|
61
|
-
"#{counter.label}(#{counter.
|
66
|
+
"#{counter.label}(#{counter.formatted_previous_table})"
|
62
67
|
}.join(", ")
|
63
68
|
max_output_length = line.length
|
64
69
|
sleep 0.7
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
70
|
+
|
71
|
+
if ENV["PBM_FOREGROUND"]
|
72
|
+
print "\r"
|
73
|
+
print " " * max_output_length
|
74
|
+
print "\r"
|
75
|
+
print line
|
76
|
+
end
|
69
77
|
ProconBypassMan.logger.debug { line }
|
70
78
|
break if $will_terminate_token
|
71
79
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class ProconBypassMan::OnMemoryCache
|
2
|
+
class CacheValue
|
3
|
+
attr_accessor :expired_at, :value
|
4
|
+
|
5
|
+
def initialize(expired_at: , value: )
|
6
|
+
self.expired_at = expired_at
|
7
|
+
self.value = value
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@table = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param [Integer] expires_in 秒数
|
16
|
+
# @param [String] key
|
17
|
+
def fetch(key: , expires_in: , &block)
|
18
|
+
now = Time.now
|
19
|
+
if @table[key].nil?
|
20
|
+
value = block.call
|
21
|
+
value_object = CacheValue.new(expired_at: now + expires_in, value: value)
|
22
|
+
@table[key] = value_object
|
23
|
+
return value
|
24
|
+
end
|
25
|
+
|
26
|
+
if @table[key].expired_at < now
|
27
|
+
value = block.call
|
28
|
+
@table[key] = CacheValue.new(expired_at: now + expires_in, value: value)
|
29
|
+
return value
|
30
|
+
else
|
31
|
+
return @table[key].value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class ProconBypassMan::Procon::AnalogStick
|
2
|
+
attr_accessor :neutral_position
|
3
|
+
attr_accessor :bin_x, :bin_y
|
4
|
+
|
5
|
+
def initialize(binary: )
|
6
|
+
@neutral_position = ProconBypassMan::ButtonsSettingConfiguration.instance.neutral_position
|
7
|
+
|
8
|
+
byte6 = binary[6].unpack("H*").first.to_i(16).to_s(2).rjust(8, "0")
|
9
|
+
byte7 = binary[7].unpack("H*").first.to_i(16).to_s(2).rjust(8, "0")
|
10
|
+
byte8 = binary[8].unpack("H*").first.to_i(16).to_s(2).rjust(8, "0")
|
11
|
+
|
12
|
+
self.bin_x = "#{byte7[4..7]}#{byte6}"
|
13
|
+
self.bin_y = "#{byte8}#{byte7[0..3]}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def abs_x
|
17
|
+
bin_x.to_i(2)
|
18
|
+
end
|
19
|
+
|
20
|
+
def abs_y
|
21
|
+
bin_y.to_i(2)
|
22
|
+
end
|
23
|
+
|
24
|
+
def relative_x
|
25
|
+
bin_x.to_i(2) - neutral_position.x
|
26
|
+
end
|
27
|
+
|
28
|
+
def relative_y
|
29
|
+
bin_y.to_i(2) - neutral_position.y
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
class ProconBypassMan::Procon::AnalogStickCap
|
2
|
+
class Position
|
3
|
+
attr_accessor :x, :y
|
4
|
+
|
5
|
+
def initialize(x:, y:)
|
6
|
+
@x = x.to_i
|
7
|
+
@y = y.to_i
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_binary
|
11
|
+
analog_stick_data = [
|
12
|
+
(@x & "0xff".to_i(16)),
|
13
|
+
((@y << 4) & "0xf0".to_i(16)) | ((@x >> 8) & "0x0f".to_i(16)),
|
14
|
+
(@y >> 4) & "0xff".to_i(16),
|
15
|
+
]
|
16
|
+
hex = analog_stick_data.map{ |x| x.to_s(16).rjust(2, "0") }.join
|
17
|
+
[hex].pack("H*")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(binary)
|
22
|
+
@binary = binary
|
23
|
+
@analog_stick = ProconBypassMan::Procon::AnalogStick.new(binary: binary)
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [ProconBypassMan::Procon::AnalogStickCap::Position]
|
27
|
+
def capped_position(cap_hypotenuse: )
|
28
|
+
if hypotenuse > cap_hypotenuse
|
29
|
+
relative_capped_x = cap_hypotenuse * Math.cos(rad * Math::PI / 180).abs
|
30
|
+
relative_capped_y = cap_hypotenuse * Math.sin(rad * Math::PI / 180).abs
|
31
|
+
relative_capped_x = -(relative_capped_x.abs) if relative_x.negative?
|
32
|
+
relative_capped_y = -(relative_capped_y.abs) if relative_y.negative?
|
33
|
+
return Position.new(
|
34
|
+
x: relative_capped_x + @analog_stick.neutral_position.x,
|
35
|
+
y: relative_capped_y + @analog_stick.neutral_position.y,
|
36
|
+
)
|
37
|
+
else
|
38
|
+
return position
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [ProconBypassMan::Procon::AnalogStickCap::Position]
|
43
|
+
def position
|
44
|
+
Position.new(x: abs_x, y: abs_y)
|
45
|
+
end
|
46
|
+
|
47
|
+
def abs_x; @analog_stick.abs_x; end # 0, 0からのx
|
48
|
+
def abs_y; @analog_stick.abs_y; end # 0, 0からのy
|
49
|
+
def relative_x; @analog_stick.relative_x; end
|
50
|
+
def relative_y; @analog_stick.relative_y; end
|
51
|
+
|
52
|
+
# @deprecated
|
53
|
+
def x; relative_x; end
|
54
|
+
def y; relative_y; end
|
55
|
+
|
56
|
+
def rad
|
57
|
+
(
|
58
|
+
Math.atan(relative_y / relative_x.to_f) * 180 / Math::PI
|
59
|
+
).floor(6)
|
60
|
+
end
|
61
|
+
|
62
|
+
def hypotenuse
|
63
|
+
Math.sqrt(relative_x**2 + relative_y**2).floor(6)
|
64
|
+
end
|
65
|
+
end
|
@@ -8,15 +8,20 @@ class ProconBypassMan::Procon::ButtonCollection
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
# https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/ac8093c84194b3232acb675ac1accce9bcb456a3/bluetooth_hid_notes.md
|
12
|
+
#0) Input report ID
|
13
|
+
#1) Timer. Increments very fast. Can be used to estimate excess Bluetooth latency.
|
14
|
+
#2 high nibble) Battery level. 8=full, 6=medium, 4=low, 2=critical, 0=empty. LSB=Charging.
|
15
|
+
#2 low nibble) Connection info. (con_info >> 1) & 3 - 3=JC, 0=Pro/ChrGrip. con_info & 1 - 1=Switch/USB powered.
|
11
16
|
#3) ZR R SR(right) SL(right) A B X Y
|
12
17
|
#4) Grip (none) Cap Home ThumbL ThumbR + -
|
13
18
|
#5) ZL L SL(left) SR(left) Left Right Up Down
|
14
|
-
#6) analog[0]
|
15
|
-
#7) analog[1]
|
16
|
-
#8) analog[2]
|
17
|
-
#9) analog[3]
|
18
|
-
#a) analog[4]
|
19
|
-
#b) analog[5]
|
19
|
+
#6) analog[0] Left analog stick data
|
20
|
+
#7) analog[1] Left analog stick data
|
21
|
+
#8) analog[2] Left analog stick data
|
22
|
+
#9) analog[3] Right analog stick data
|
23
|
+
#a) analog[4] Right analog stick data
|
24
|
+
#b) analog[5] Right analog stick data
|
20
25
|
BYTES_MAP = {
|
21
26
|
0 => nil,
|
22
27
|
1 => nil,
|
@@ -24,11 +29,15 @@ class ProconBypassMan::Procon::ButtonCollection
|
|
24
29
|
3 => [:zr, :r, :sr, :sl, :a, :b, :x, :y],
|
25
30
|
4 => [:grip, :_undefined_key, :cap, :home, :thumbl, :thumbr, :plus, :minus],
|
26
31
|
5 => [:zl, :l, :sl, :sr, :left, :right, :up, :down],
|
32
|
+
6 => [],
|
33
|
+
7 => [],
|
34
|
+
8 => [],
|
27
35
|
}.freeze
|
28
36
|
|
29
37
|
BUTTONS_MAP = BYTES_MAP.reduce({}) { |acc, value|
|
30
38
|
next acc if value[1].nil?
|
31
39
|
value[1].reverse.each.with_index do |button, index|
|
40
|
+
next(acc) if button == :grip || button == :_undefined_key
|
32
41
|
acc[button] = { byte_position: value[0], bit_position: index }
|
33
42
|
end
|
34
43
|
acc
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class ProconBypassMan::Procon::LayerChanger
|
2
|
+
def initialize(binary: )
|
3
|
+
@procon_reader = ProconBypassMan::ProconReader.new(binary: binary)
|
4
|
+
end
|
5
|
+
|
6
|
+
# @return [Symbol]
|
7
|
+
def next_layer_key
|
8
|
+
case
|
9
|
+
when pressed?(button: :up)
|
10
|
+
:up
|
11
|
+
when pressed?(button: :right)
|
12
|
+
:right
|
13
|
+
when pressed?(button: :left)
|
14
|
+
:left
|
15
|
+
when pressed?(button: :down)
|
16
|
+
:down
|
17
|
+
else
|
18
|
+
ProconBypassMan.logger.warn("next_layer_key is unknown")
|
19
|
+
:up
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Boolean]
|
24
|
+
def change_layer?
|
25
|
+
if ProconBypassMan::ButtonsSettingConfiguration.instance.prefix_keys.empty?
|
26
|
+
raise "prefix_keysが未設定です"
|
27
|
+
end
|
28
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance.prefix_keys.map { |b| pressed?(button: b) }.all?
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Boolean]
|
32
|
+
def pressed_next_layer?
|
33
|
+
change_layer? && (pressed?(button: :up) || pressed?(button: :right) || pressed?(button: :left) || pressed?(button: :down))
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [Boolean]
|
37
|
+
def pressed?(button: )
|
38
|
+
@procon_reader.pressed.include?(button)
|
39
|
+
end
|
40
|
+
end
|
@@ -37,11 +37,11 @@ class ProconBypassMan::Procon::MacroRegistry
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def self.reset!
|
40
|
-
ProconBypassMan::
|
40
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance.macro_plugins = {}
|
41
41
|
end
|
42
42
|
|
43
43
|
def self.plugins
|
44
|
-
ProconBypassMan::
|
44
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance.macro_plugins
|
45
45
|
end
|
46
46
|
|
47
47
|
reset!
|
@@ -23,10 +23,10 @@ class ProconBypassMan::Procon::ModeRegistry
|
|
23
23
|
}
|
24
24
|
|
25
25
|
def self.install_plugin(klass)
|
26
|
-
if plugins[klass.name]
|
26
|
+
if plugins[klass.name.to_sym]
|
27
27
|
raise "すでに登録済みです"
|
28
28
|
end
|
29
|
-
plugins[klass.name] = klass.binaries
|
29
|
+
plugins[klass.name.to_sym] = klass.binaries
|
30
30
|
end
|
31
31
|
|
32
32
|
def self.load(name)
|
@@ -35,11 +35,11 @@ class ProconBypassMan::Procon::ModeRegistry
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def self.reset!
|
38
|
-
ProconBypassMan::
|
38
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance.mode_plugins = {}
|
39
39
|
end
|
40
40
|
|
41
41
|
def self.plugins
|
42
|
-
ProconBypassMan::
|
42
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance.mode_plugins
|
43
43
|
end
|
44
44
|
|
45
45
|
reset!
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class ProconBypassMan::PpressButtonAware
|
2
|
+
def initialize(binary)
|
3
|
+
@binary = binary
|
4
|
+
end
|
5
|
+
|
6
|
+
def pressed_button?(button)
|
7
|
+
@binary[
|
8
|
+
::ProconBypassMan::Procon::ButtonCollection.load(button).byte_position
|
9
|
+
].unpack("H*").first.to_i(16).to_s(2).reverse[
|
10
|
+
::ProconBypassMan::Procon::ButtonCollection.load(button).bit_position
|
11
|
+
] == '1'
|
12
|
+
end
|
13
|
+
end
|