@@ -80,7 +80,7 @@ class PloverHid(ThreadedStenotypeBase):
8080 def __init__ (self , params ):
8181 super ().__init__ ()
8282 self ._params = params
83- self ._hid = None
83+ self ._hids = []
8484
8585 def _parse (self , report ):
8686 # The first byte is the report id, and due to idiosyncrasies
@@ -102,7 +102,7 @@ def send(self, key_state):
102102 def run (self ):
103103 self ._ready ()
104104
105- if not self ._hid :
105+ if not self ._hids :
106106 log .error ("no HID available" )
107107 self ._error ()
108108 return
@@ -114,12 +114,24 @@ def run(self):
114114 sent_first_up = False
115115 while not self .finished .wait (0 ):
116116 interval_ms = self ._params ["repeat_interval_ms" ]
117- try :
118- report = self ._hid .read (65536 , interval_ms )
119- except Exception as e :
120- log .error (f"exception during run: { e } " )
121- self ._error ()
122- return
117+
118+ report = None
119+ # Poll all devices: block on the first, then non-blocking on the rest
120+ for idx , dev in enumerate (list (self ._hids )):
121+ try :
122+ r = dev .read (65536 , interval_ms if idx == 0 else 0 )
123+ except Exception as e :
124+ log .debug (f"exception during run: { e } " )
125+ try :
126+ dev .close ()
127+ except Exception :
128+ pass
129+ self ._hids .remove (dev )
130+ continue
131+ if r :
132+ report = r
133+ break
134+
123135 if not report :
124136 # The set of keys pressed down hasn't changed. Figure out if we need to be sending repeats:
125137 if (
@@ -131,7 +143,12 @@ def run(self):
131143 self .send (current )
132144 # Avoid sending an extra chord when the repeated chord is released.
133145 sent_first_up = True
146+ # If all devices are gone, stop.
147+ if not self ._hids :
148+ self ._error ()
149+ return
134150 continue
151+
135152 try :
136153 current = self ._parse (report )
137154 except InvalidReport :
@@ -174,10 +191,7 @@ def start_capture(self):
174191 log .info ("no device found" )
175192 return
176193
177- # FIXME: if multiple compatible devices are found we should either
178- # let the end user configure which one they want, or support reading
179- # from all connected plover hid devices at the same time.
180- self ._hid = hid .Device (path = devices [0 ])
194+ self ._hids = [hid .Device (path = path ) for path in devices ]
181195 except Exception as e :
182196 self ._error ()
183197 log .error (f"error during start of capture: { e } " )
@@ -186,15 +200,19 @@ def start_capture(self):
186200
187201 def stop_capture (self ):
188202 super ().stop_capture ()
189- if self ._hid :
190- self ._hid .close ()
191- self ._hid = None
203+ for dev in self ._hids :
204+ try :
205+ dev .close ()
206+ except Exception as e :
207+ log .debug (f"error while closing device: { e } " )
208+ pass
209+ self ._hids = []
192210
193211 @classmethod
194212 def get_option_info (cls ):
195213 return {
196214 "first_up_chord_send" : (False , boolean ),
197215 "double_tap_repeat" : (False , boolean ),
198216 "repeat_delay_ms" : (200 , int ),
199- "repeat_interval_ms" : (50 , int ),
217+ "repeat_interval_ms" : (30 , int ),
200218 }
0 commit comments