procon_bypass_man 0.1.6 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +41 -16
- data/.github/workflows/ruby.yml +34 -0
- data/.gitignore +4 -0
- data/.rubocop.yml +2 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +17 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +57 -6
- data/README.md +18 -10
- data/Rakefile +10 -1
- data/Steepfile +39 -0
- data/bin/report_receive_server.rb +11 -0
- data/docs/setup_raspi.md +12 -7
- data/docs/setup_raspi.mitamae.rb +60 -0
- data/docs/setup_raspi_by_mitamae.md +14 -0
- data/lib/procon_bypass_man/analog_stick_position.rb +8 -0
- data/lib/procon_bypass_man/boot_message.rb +40 -0
- data/lib/procon_bypass_man/buttons_setting_configuration.rb +100 -0
- data/lib/procon_bypass_man/bypass/usb_hid_logger.rb +20 -0
- data/lib/procon_bypass_man/bypass.rb +61 -29
- data/lib/procon_bypass_man/callbacks.rb +70 -0
- data/lib/procon_bypass_man/configuration/layer.rb +50 -4
- data/lib/procon_bypass_man/configuration/loader.rb +8 -8
- data/lib/procon_bypass_man/configuration/validator.rb +1 -1
- data/lib/procon_bypass_man/configuration.rb +68 -64
- data/lib/procon_bypass_man/device_connector.rb +13 -30
- data/lib/procon_bypass_man/io_monitor.rb +7 -4
- data/lib/procon_bypass_man/on_memory_cache.rb +34 -0
- data/lib/procon_bypass_man/outbound/base.rb +40 -0
- data/lib/procon_bypass_man/outbound/error_reporter.rb +13 -0
- data/lib/procon_bypass_man/outbound/reporter.rb +12 -0
- data/lib/procon_bypass_man/outbound/usb_hid_data_reporter.rb +13 -0
- data/lib/procon_bypass_man/procon/analog_stick_cap.rb +88 -0
- data/lib/procon_bypass_man/procon/button_collection.rb +14 -6
- data/lib/procon_bypass_man/procon/debug_dumper.rb +17 -0
- data/lib/procon_bypass_man/procon/layer_changeable.rb +2 -2
- 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/pressed_button_helper.rb +0 -10
- data/lib/procon_bypass_man/procon/user_operation.rb +14 -3
- data/lib/procon_bypass_man/procon.rb +23 -5
- data/lib/procon_bypass_man/runner.rb +36 -48
- data/lib/procon_bypass_man/uptime.rb +15 -0
- data/lib/procon_bypass_man/version.rb +1 -1
- data/lib/procon_bypass_man.rb +26 -33
- data/project_template/README.md +17 -0
- data/project_template/app.rb +20 -0
- data/project_template/setting.yml +35 -0
- data/project_template/systemd_units/pbm.service +13 -0
- 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 +507 -0
- metadata +30 -5
- data/examples/pbm.service +0 -27
- data/examples/simple.rb +0 -13
@@ -0,0 +1,20 @@
|
|
1
|
+
class ProconBypassMan::Bypass
|
2
|
+
module UsbHidLogger
|
3
|
+
extend ProconBypassMan::Callbacks::ClassMethods
|
4
|
+
include ProconBypassMan::Callbacks
|
5
|
+
|
6
|
+
define_callbacks :send_gadget_to_procon
|
7
|
+
define_callbacks :send_procon_to_gadget
|
8
|
+
|
9
|
+
set_callback :send_gadget_to_procon, :after, :log_send_gadget_to_procon
|
10
|
+
set_callback :send_procon_to_gadget, :after, :log_procon_to_gadget
|
11
|
+
|
12
|
+
def log_send_gadget_to_procon
|
13
|
+
ProconBypassMan.logger.debug { ">>> #{bypass_status.to_text}" }
|
14
|
+
end
|
15
|
+
|
16
|
+
def log_procon_to_gadget
|
17
|
+
ProconBypassMan.logger.debug { "<<< #{bypass_status.to_text}" }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,5 +1,16 @@
|
|
1
|
+
require "procon_bypass_man/bypass/usb_hid_logger"
|
2
|
+
|
1
3
|
class ProconBypassMan::Bypass
|
2
|
-
|
4
|
+
include ProconBypassMan::Bypass::UsbHidLogger
|
5
|
+
|
6
|
+
class BypassStatus < Struct.new(:binary, :sent)
|
7
|
+
def to_text
|
8
|
+
"#{binary.unpack("H*").first} #{'x' unless sent}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_accessor :gadget, :procon, :monitor, :bypass_status
|
13
|
+
|
3
14
|
def initialize(gadget: , procon: , monitor: )
|
4
15
|
self.gadget = gadget
|
5
16
|
self.procon = procon
|
@@ -10,43 +21,64 @@ class ProconBypassMan::Bypass
|
|
10
21
|
def send_gadget_to_procon!
|
11
22
|
monitor.record(:start_function)
|
12
23
|
input = nil
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
24
|
+
self.bypass_status = BypassStatus.new(input, sent = false)
|
25
|
+
|
26
|
+
run_callbacks :send_gadget_to_procon do
|
27
|
+
begin
|
28
|
+
return if $will_terminate_token
|
29
|
+
# TODO blocking readにしたいが、接続時のフェーズによって長さが違宇野で厳しい
|
30
|
+
input = self.gadget.read_nonblock(64)
|
31
|
+
self.bypass_status.binary = input
|
32
|
+
rescue IO::EAGAINWaitReadable
|
33
|
+
monitor.record(:eagain_wait_readable_on_read)
|
34
|
+
sleep(0.001)
|
35
|
+
retry
|
36
|
+
end
|
22
37
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
38
|
+
begin
|
39
|
+
self.procon.write_nonblock(input)
|
40
|
+
self.bypass_status.sent = true
|
41
|
+
rescue IO::EAGAINWaitReadable
|
42
|
+
monitor.record(:eagain_wait_readable_on_write)
|
43
|
+
return
|
44
|
+
end
|
28
45
|
end
|
46
|
+
|
29
47
|
monitor.record(:end_function)
|
30
48
|
end
|
31
49
|
|
32
50
|
def send_procon_to_gadget!
|
33
51
|
monitor.record(:start_function)
|
34
52
|
output = nil
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
53
|
+
self.bypass_status = BypassStatus.new(output, sent = false)
|
54
|
+
|
55
|
+
run_callbacks(:send_procon_to_gadget) do
|
56
|
+
begin
|
57
|
+
return if $will_terminate_token
|
58
|
+
Timeout.timeout(1) do
|
59
|
+
output = self.procon.read(64)
|
60
|
+
self.bypass_status.binary = output
|
61
|
+
end
|
62
|
+
rescue Timeout::Error
|
63
|
+
ProconBypassMan.logger.debug { "read timeout! do sleep. by send_procon_to_gadget!" }
|
64
|
+
ProconBypassMan.error_logger.error { "read timeout! do sleep. by send_procon_to_gadget!" }
|
65
|
+
monitor.record(:eagain_wait_readable_on_read)
|
66
|
+
retry
|
67
|
+
rescue IO::EAGAINWaitReadable
|
68
|
+
ProconBypassMan.logger.debug { "EAGAINWaitReadable" }
|
69
|
+
monitor.record(:eagain_wait_readable_on_read)
|
70
|
+
sleep(0.005)
|
71
|
+
retry
|
72
|
+
end
|
44
73
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
74
|
+
begin
|
75
|
+
# ProconBypassMan::Procon::DebugDumper.new(binary: output).dump_analog_sticks
|
76
|
+
self.gadget.write_nonblock(ProconBypassMan::Processor.new(output).process)
|
77
|
+
self.bypass_status.sent = true
|
78
|
+
rescue IO::EAGAINWaitReadable
|
79
|
+
monitor.record(:eagain_wait_readable_on_write)
|
80
|
+
return
|
81
|
+
end
|
50
82
|
end
|
51
83
|
monitor.record(:end_function)
|
52
84
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module ProconBypassMan
|
2
|
+
module Callbacks
|
3
|
+
class CallbacksChain
|
4
|
+
attr_accessor :filter, :chain_method
|
5
|
+
def initialize(filter: , chain_method: , block: )
|
6
|
+
@filter = filter
|
7
|
+
@chain_method = chain_method
|
8
|
+
@block = block
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# TODO __callbacksをincludeしたクラス側で保持する. 今はnemespaceがない
|
13
|
+
module M
|
14
|
+
class << self
|
15
|
+
attr_accessor :__callbacks
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
def define_callbacks(name)
|
21
|
+
self.singleton_class.attr_accessor "_#{name}_callbacks"
|
22
|
+
send "_#{name}_callbacks=", [name] # CallbacksChain
|
23
|
+
|
24
|
+
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
25
|
+
def _run_#{name}_callbacks(&block)
|
26
|
+
__run_callbacks__(_#{name}_callbacks, &block)
|
27
|
+
end
|
28
|
+
RUBY
|
29
|
+
end
|
30
|
+
|
31
|
+
def set_callback(kind, filter, chain_method, &block)
|
32
|
+
ProconBypassMan::Callbacks::M.__callbacks ||= {}
|
33
|
+
ProconBypassMan::Callbacks::M.__callbacks[kind] = CallbacksChain.new(
|
34
|
+
filter: filter,
|
35
|
+
chain_method: chain_method,
|
36
|
+
block: block,
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# TODO haltしたらcallbackを止める
|
42
|
+
# TODO 複数をチェインできるようにする
|
43
|
+
def run_callbacks(kind, &block)
|
44
|
+
chain = get_callbacks(kind) or raise("unknown callback")
|
45
|
+
case chain.filter
|
46
|
+
when :before
|
47
|
+
send chain.chain_method
|
48
|
+
block.call
|
49
|
+
when :after
|
50
|
+
block.call
|
51
|
+
send chain.chain_method
|
52
|
+
else
|
53
|
+
raise("unknown filter")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# def __run_callbacks__(name, &block)
|
58
|
+
# puts "called"
|
59
|
+
# end
|
60
|
+
|
61
|
+
def get_callbacks(kind) # :nodoc:
|
62
|
+
ProconBypassMan::Callbacks::M.__callbacks[kind.to_sym]
|
63
|
+
end
|
64
|
+
|
65
|
+
def set_callbacks(name, callbacks) # :nodoc:
|
66
|
+
send "_#{name}_callbacks=", callbacks
|
67
|
+
ProconBypassMan::Callbacks::M.__callbacks[kind.to_sym] = callbacks
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -1,13 +1,15 @@
|
|
1
1
|
module ProconBypassMan
|
2
|
-
class
|
2
|
+
class ButtonsSettingConfiguration
|
3
3
|
class Layer
|
4
|
-
attr_accessor :mode, :flips, :macros, :remaps
|
4
|
+
attr_accessor :mode, :flips, :macros, :remaps, :left_analog_stick_caps, :disables
|
5
5
|
|
6
|
-
def initialize(mode: :manual
|
6
|
+
def initialize(mode: :manual)
|
7
7
|
self.mode = mode
|
8
8
|
self.flips = {}
|
9
9
|
self.macros = {}
|
10
10
|
self.remaps = {}
|
11
|
+
self.left_analog_stick_caps = {}
|
12
|
+
self.disables = []
|
11
13
|
instance_eval(&block) if block_given?
|
12
14
|
end
|
13
15
|
|
@@ -50,7 +52,6 @@ module ProconBypassMan
|
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
53
|
-
PRESET_MACROS = [:fast_return]
|
54
55
|
def macro(name, if_pressed: )
|
55
56
|
if name.respond_to?(:name)
|
56
57
|
macro_name = name.name.to_sym
|
@@ -72,6 +73,51 @@ module ProconBypassMan
|
|
72
73
|
end
|
73
74
|
end
|
74
75
|
|
76
|
+
def left_analog_stick_cap(cap: , if_pressed: nil, force_neutral: nil)
|
77
|
+
hash = { cap: cap }
|
78
|
+
|
79
|
+
case if_pressed
|
80
|
+
when TrueClass
|
81
|
+
raise "not support class"
|
82
|
+
when Symbol, String
|
83
|
+
if_pressed = [if_pressed]
|
84
|
+
when Array, FalseClass
|
85
|
+
# sono mama
|
86
|
+
when NilClass
|
87
|
+
if_pressed = nil
|
88
|
+
else
|
89
|
+
raise "not support if_pressed"
|
90
|
+
end
|
91
|
+
|
92
|
+
if force_neutral
|
93
|
+
case force_neutral
|
94
|
+
when TrueClass, FalseClass
|
95
|
+
raise "ボタンを渡してください"
|
96
|
+
when Symbol, String
|
97
|
+
hash[:force_neutral] = [force_neutral]
|
98
|
+
when Array
|
99
|
+
hash[:force_neutral] = force_neutral
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
left_analog_stick_caps[if_pressed] = hash
|
104
|
+
end
|
105
|
+
|
106
|
+
def disable(button)
|
107
|
+
case button
|
108
|
+
when TrueClass, FalseClass, NilClass
|
109
|
+
raise "not support class"
|
110
|
+
when Symbol
|
111
|
+
disables << button
|
112
|
+
when String
|
113
|
+
disables << button.to_sym
|
114
|
+
when Array
|
115
|
+
button.each { |b| disables << b }
|
116
|
+
else
|
117
|
+
raise "unknown"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
75
121
|
# @return [Array]
|
76
122
|
def flip_buttons
|
77
123
|
flips
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module ProconBypassMan
|
2
|
-
class
|
2
|
+
class ButtonsSettingConfiguration
|
3
3
|
module Loader
|
4
4
|
require 'digest/md5'
|
5
5
|
|
6
6
|
def self.load(setting_path: )
|
7
|
-
ProconBypassMan::
|
7
|
+
ProconBypassMan::ButtonsSettingConfiguration.switch_new_context(:validation) do |validation_instance|
|
8
8
|
yaml = YAML.load_file(setting_path) or raise "読み込みに失敗しました"
|
9
9
|
validation_instance.instance_eval(yaml["setting"])
|
10
10
|
validator = Validator.new(validation_instance)
|
@@ -20,25 +20,25 @@ module ProconBypassMan
|
|
20
20
|
end
|
21
21
|
|
22
22
|
yaml = YAML.load_file(setting_path)
|
23
|
-
ProconBypassMan::
|
24
|
-
ProconBypassMan::
|
23
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance.setting_path = setting_path
|
24
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance.reset!
|
25
25
|
ProconBypassMan.reset!
|
26
26
|
|
27
27
|
case yaml["version"]
|
28
28
|
when 1.0, nil
|
29
|
-
ProconBypassMan::
|
29
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance.instance_eval(yaml["setting"])
|
30
30
|
else
|
31
31
|
ProconBypassMan.logger.warn "不明なバージョンです。failoverします"
|
32
|
-
ProconBypassMan::
|
32
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance.instance_eval(yaml["setting"])
|
33
33
|
end
|
34
34
|
|
35
35
|
File.write(ProconBypassMan.digest_path, Digest::MD5.hexdigest(yaml["setting"]))
|
36
36
|
|
37
|
-
ProconBypassMan::
|
37
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance
|
38
38
|
end
|
39
39
|
|
40
40
|
def self.reload_setting
|
41
|
-
self.load(setting_path: ProconBypassMan::
|
41
|
+
self.load(setting_path: ProconBypassMan::ButtonsSettingConfiguration.instance.setting_path)
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
@@ -1,86 +1,90 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
class ProconBypassMan::Configuration
|
2
|
+
module ClassAttributes
|
3
|
+
def root
|
4
|
+
config.root
|
5
|
+
end
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
+
def logger
|
8
|
+
config.logger
|
9
|
+
end
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
:macro_plugins,
|
12
|
-
:context,
|
13
|
-
:current_context_key
|
11
|
+
def error_logger
|
12
|
+
config.error_logger
|
13
|
+
end
|
14
14
|
|
15
|
-
def
|
16
|
-
@@
|
17
|
-
@@context ||= {}
|
18
|
-
@@context[@@current_context_key] ||= new
|
15
|
+
def pid_path
|
16
|
+
@@pid_path ||= File.expand_path("#{root}/pbm_pid", __dir__).freeze
|
19
17
|
end
|
20
18
|
|
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
|
19
|
+
def digest_path
|
20
|
+
config.digest_path
|
32
21
|
end
|
33
22
|
|
34
|
-
def
|
35
|
-
|
23
|
+
def cache
|
24
|
+
@@cache_table ||= ProconBypassMan::OnMemoryCache.new
|
36
25
|
end
|
26
|
+
end
|
37
27
|
|
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
|
28
|
+
attr_reader :api_server
|
29
|
+
attr_accessor :enable_critical_error_logging
|
48
30
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
31
|
+
def root=(path)
|
32
|
+
@root = path
|
33
|
+
return self
|
34
|
+
end
|
54
35
|
|
55
|
-
|
56
|
-
|
57
|
-
|
36
|
+
def root
|
37
|
+
if defined?(@root)
|
38
|
+
@root
|
39
|
+
else
|
40
|
+
File.expand_path('..', __dir__ || ".").freeze
|
58
41
|
end
|
42
|
+
end
|
59
43
|
|
60
|
-
|
61
|
-
|
62
|
-
|
44
|
+
def api_server=(api_server)
|
45
|
+
@api_server = api_server
|
46
|
+
return self
|
47
|
+
end
|
48
|
+
|
49
|
+
def logger=(logger)
|
50
|
+
@logger = logger
|
51
|
+
return self
|
52
|
+
end
|
53
|
+
|
54
|
+
def logger
|
55
|
+
if ENV["PBM_ENV"] == 'test'
|
56
|
+
return Logger.new($stdout)
|
63
57
|
end
|
64
58
|
|
65
|
-
|
66
|
-
@
|
67
|
-
|
59
|
+
if defined?(@logger) && @logger.is_a?(Logger)
|
60
|
+
@logger
|
61
|
+
else
|
62
|
+
Logger.new(File.open("/dev/null"))
|
68
63
|
end
|
64
|
+
end
|
69
65
|
|
70
|
-
|
71
|
-
|
66
|
+
def error_logger
|
67
|
+
if enable_critical_error_logging
|
68
|
+
@@error_logger ||= Logger.new("#{ProconBypassMan.root}/error.log", 5, 1024 * 1024 * 10)
|
69
|
+
else
|
70
|
+
Logger.new(File.open("/dev/null"))
|
72
71
|
end
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
75
|
+
def digest_path
|
76
|
+
"#{root}/.setting_yaml_digest"
|
77
|
+
end
|
73
78
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
}
|
79
|
+
# @return [String] pbm-webの接続先
|
80
|
+
def internal_api_servers
|
81
|
+
if !!ENV["INTERNAL_API_SERVER"]
|
82
|
+
[ENV["INTERNAL_API_SERVER"]]
|
83
|
+
else
|
84
|
+
[ ENV["INTERNAL_API_SERVER"],
|
85
|
+
'http://localhost:9090',
|
86
|
+
'http://localhost:8080',
|
87
|
+
].compact
|
84
88
|
end
|
85
89
|
end
|
86
90
|
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([
|
@@ -37,16 +20,16 @@ class ProconBypassMan::DeviceConnector
|
|
37
20
|
["8005"],
|
38
21
|
["0010"],
|
39
22
|
], read_from: :switch)
|
40
|
-
# 1
|
23
|
+
# 1. Sends current connection status, and if the Joy-Con are connected,
|
41
24
|
s.add([["8001"]], read_from: :switch)
|
42
25
|
s.add([/^8101/], read_from: :procon) # <<< 81010003176d96e7a5480000000, macaddressとコントローラー番号を返す
|
43
|
-
# 2
|
26
|
+
# 2. Sends handshaking packets over UART to the Joy-Con or Pro Controller Broadcom chip. This command can only be called once per session.
|
44
27
|
s.add([["8002"]], read_from: :switch)
|
45
28
|
s.add([/^8102/], read_from: :procon)
|
46
29
|
# 3
|
47
30
|
s.add([/^0100/], read_from: :switch)
|
48
31
|
s.add([/^21/], read_from: :procon)
|
49
|
-
# 4
|
32
|
+
# 4. Forces the Joy-Con or Pro Controller to only talk over USB HID without any timeouts. This is required for the Pro Controller to not time out and revert to Bluetooth.
|
50
33
|
s.add([["8004"]], read_from: :switch)
|
51
34
|
s.drain_all
|
52
35
|
return [s.switch, s.procon]
|
@@ -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
|
@@ -62,10 +62,13 @@ module ProconBypassMan
|
|
62
62
|
}.join(", ")
|
63
63
|
max_output_length = line.length
|
64
64
|
sleep 0.7
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
|
66
|
+
if ENV["PBM_FOREGROUND"]
|
67
|
+
print "\r"
|
68
|
+
print " " * max_output_length
|
69
|
+
print "\r"
|
70
|
+
print line
|
71
|
+
end
|
69
72
|
ProconBypassMan.logger.debug { line }
|
70
73
|
break if $will_terminate_token
|
71
74
|
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
|