185185# transparent pixels in the corners for the rounded corner effect
186186exit_btn_bmp .pixel_shader .make_transparent (0 )
187187
188- # centered within the display, offset to the right
189- exit_btn .x = display .width // scale_factor // 2 - (exit_btn_bmp .width ) // 2 + 30
190-
191- # inside the bounds of the game over label, so it looks like a dialog visually
192- exit_btn .y = 100
193-
194188# add the play again and exit buttons to the game over group
195189game_over_group .append (play_again_btn )
196- game_over_group .append (exit_btn )
197190main_group .append (game_over_group )
198191
192+ # Along right border
193+ exit_btn .x = display .width // scale_factor - (exit_btn_bmp .width )
194+ exit_btn .y = 100
195+ main_group .append (exit_btn )
196+
199197# wait a second for USB devices to be ready
200198time .sleep (1 )
201199
247245# USB info lists
248246mouse_interface_indexes = []
249247mouse_endpoint_addresses = []
250- kernel_driver_active_flags = []
248+ detached_interfaces = []
251249# USB device object instance list
252250mice = []
253251# buffers list for mouse packet data
257255mouse_sync = []
258256
259257# scan for connected USB devices
260- for device in usb .core .find (find_all = True ):
261- # check if current device is has a boot mouse endpoint
262- try :
263- mouse_interface_index , mouse_endpoint_address = (
264- adafruit_usb_host_descriptors .find_boot_mouse_endpoint (device )
265- )
266- if mouse_interface_index is not None and mouse_endpoint_address is not None :
267- # if it does have a boot mouse endpoint then add information to the
268- # usb info lists
269- mouse_interface_indexes .append (mouse_interface_index )
270- mouse_endpoint_addresses .append (mouse_endpoint_address )
271-
272- # add the mouse device instance to list
273- mice .append (device )
274- print (
275- f"mouse interface: { mouse_interface_index } "
276- + f"endpoint_address: { hex (mouse_endpoint_address )} "
277- )
278- mouse_sync .append (0 )
279-
280- # detach kernel driver if needed
281- kernel_driver_active_flags .append (device .is_kernel_driver_active (0 ))
282- if device .is_kernel_driver_active (0 ):
283- device .detach_kernel_driver (0 )
284-
285- # set the mouse configuration so it can be used
286- device .set_configuration ()
287-
288- except usb .core .USBError as e :
289- # The mouse might have glitched and may not be detected but at least we don't crash
290- print (e )
258+ for find_endpoint , default_sync in [
259+ (adafruit_usb_host_descriptors .find_boot_mouse_endpoint , 0 ),
260+ (adafruit_usb_host_descriptors .find_report_mouse_endpoint , - 1 )
261+ ]:
262+
263+ for device in usb .core .find (find_all = True ):
264+ if device in mice :
265+ print ('found device twice' )
266+ continue
267+ # check if current device is has a boot mouse endpoint
268+ try :
269+ mouse_interface_index , mouse_endpoint_address = (find_endpoint (device ))
270+ if mouse_interface_index is not None and mouse_endpoint_address is not None :
271+ if (
272+ mouse_interface_index in mouse_interface_indexes and
273+ mouse_endpoint_address in mouse_endpoint_addresses
274+ ):
275+ print ('found index/address twice' )
276+ continue
277+ # if it does have a mouse endpoint then add information to the
278+ # usb info lists
279+ mouse_interface_indexes .append (mouse_interface_index )
280+ mouse_endpoint_addresses .append (mouse_endpoint_address )
281+
282+ # add the mouse device instance to list
283+ mice .append (device )
284+ print (
285+ f"{ default_sync } mouse interface: { mouse_interface_index } "
286+ + f"endpoint_address: { hex (mouse_endpoint_address )} "
287+ )
288+ mouse_sync .append (default_sync )
289+
290+ # detach kernel driver if needed
291+ detached = []
292+
293+ # Typically HID devices have interfaces 0,1,2
294+ for intf in range (3 ):
295+ print (f'interface: { intf } ' ,end = "" )
296+ try :
297+ if device .is_kernel_driver_active (intf ):
298+ device .detach_kernel_driver (intf )
299+ detached .append (intf )
300+ print (f"Detached kernel driver from interface { intf } " )
301+ else :
302+ print ("not active" )
303+ except usb .core .USBError as e :
304+ print (e )
305+
306+ detached_interfaces .append (detached )
307+
308+ except usb .core .USBError as e :
309+ # The mouse might have glitched and may not be detected but at least we don't crash
310+ print (e )
311+
312+ if len (mice ) >= 2 :
313+ break
314+
315+ if len (mice ) >= 2 :
316+ break
317+
318+ # set the mouse configuration on any detected mice so they can be used
319+ for device in mice :
320+ device .set_configuration ()
291321
292322def is_mouse1_left_clicked ():
293323 """
@@ -356,7 +386,11 @@ def get_mouse_deltas(buffer, read_count, sync):
356386 :param read_count: the number of bytes read from the mouse
357387 :return: tuple containing x and y delta values
358388 """
359- if read_count == 4 or (read_count == 8 and sync > 50 ):
389+
390+ if read_count == 6 and sync == - 1 :
391+ delta_x = buffer [2 ]
392+ delta_y = buffer [3 ]
393+ elif read_count == 4 or (read_count == 8 and sync > 50 ):
360394 delta_x = buffer [1 ]
361395 delta_y = buffer [2 ]
362396 elif read_count == 8 :
@@ -378,9 +412,16 @@ def atexit_callback():
378412 :return:
379413 """
380414 for _i , _mouse in enumerate (mice ):
381- if kernel_driver_active_flags [_i ]:
382- if not _mouse .is_kernel_driver_active (0 ):
383- _mouse .attach_kernel_driver (0 )
415+ detached_from_device = detached_interfaces [_i ]
416+
417+ if detached_from_device :
418+ for _intf in detached_from_device :
419+ if not _mouse .is_kernel_driver_active (_intf ):
420+ _mouse .attach_kernel_driver (_intf )
421+ print (f'#{ _i } Index: { _intf } (reattaching)' )
422+ else :
423+ print (f'#{ _i } Index: { _intf } (Not Attaching)' )
424+
384425 supervisor .runtime .autoreload = original_autoreload_val
385426
386427
@@ -407,6 +448,8 @@ def atexit_callback():
407448 )
408449 mouse_deltas = get_mouse_deltas (mouse_bufs [i ], data_len , mouse_sync [i ])
409450 mouse_sync [i ] = mouse_deltas [2 ]
451+ if mouse_sync [i ] == - 1 :
452+ mouse_bufs [i ][0 ] = mouse_bufs [i ][1 ]
410453 # if we got data, then update the mouse cursor on the display
411454 # using min and max to keep it within the bounds of the display
412455 mouse_tg .x = max (
@@ -445,6 +488,11 @@ def atexit_callback():
445488 # get the current mouse coordinates
446489 coords = (mouse_tg .x , mouse_tg .y , 0 )
447490
491+ # if the mouse point is within the exit
492+ # button bounding box
493+ if exit_btn .contains (coords ):
494+ supervisor .reload ()
495+
448496 # if the current state is GAMEOVER
449497 if match3_game .cur_state != STATE_GAMEOVER :
450498 # let the game object handle the click event
@@ -458,11 +506,6 @@ def atexit_callback():
458506 # reload
459507 supervisor .reload ()
460508
461- # if the mouse point is within the exit
462- # button bounding box
463- if exit_btn .contains (coords ):
464- supervisor .reload ()
465-
466509 # if the game is over
467510 except GameOverException :
468511 # check for a winner
@@ -483,6 +526,10 @@ def atexit_callback():
483526 # show a tie game message
484527 message = "\n Game Over\n Tie Game Everyone Wins!"
485528
529+ # centered within the display, offset to the right
530+ # inside the bounds of the game over label, so it looks like a dialog visually
531+ exit_btn .x = display .width // scale_factor // 2 - (exit_btn_bmp .width ) // 2 + 30
532+ exit_btn .y = 100
486533 # make the gameover group visible
487534 game_over_group .hidden = False
488535
0 commit comments