()
| 627 | |
| 628 | #[cfg(target_os = "linux")] |
| 629 | fn poll_linux_gamepad() { |
| 630 | unsafe { |
| 631 | // Try to open gamepad if not already |
| 632 | if GAMEPAD_FD < 0 { |
| 633 | let path = b"/dev/input/js0\0"; |
| 634 | // Open non-blocking |
| 635 | GAMEPAD_FD = libc::open(path.as_ptr() as *const libc::c_char, libc::O_RDONLY | libc::O_NONBLOCK); |
| 636 | if GAMEPAD_FD >= 0 { |
| 637 | engine().input.gamepad_available = true; |
| 638 | engine().input.gamepad_axis_count = 6; |
| 639 | } |
| 640 | } |
| 641 | if GAMEPAD_FD < 0 { return; } |
| 642 | |
| 643 | // Linux joystick event structure |
| 644 | #[repr(C)] |
| 645 | struct JsEvent { |
| 646 | time: u32, |
| 647 | value: i16, |
| 648 | event_type: u8, |
| 649 | number: u8, |
| 650 | } |
| 651 | |
| 652 | loop { |
| 653 | let mut event = std::mem::zeroed::<JsEvent>(); |
| 654 | let n = libc::read( |
| 655 | GAMEPAD_FD, |
| 656 | &mut event as *mut _ as *mut libc::c_void, |
| 657 | std::mem::size_of::<JsEvent>(), |
| 658 | ); |
| 659 | if n != std::mem::size_of::<JsEvent>() as isize { break; } |
| 660 | |
| 661 | let type_masked = event.event_type & 0x7f; // strip JS_EVENT_INIT |
| 662 | if type_masked == 1 { |
| 663 | // Button |
| 664 | let idx = event.number as usize; |
| 665 | if event.value != 0 { |
| 666 | engine().input.set_gamepad_button_down(idx); |
| 667 | } else { |
| 668 | engine().input.set_gamepad_button_up(idx); |
| 669 | } |
| 670 | } else if type_masked == 2 { |
| 671 | // Axis |
| 672 | let idx = event.number as usize; |
| 673 | let value = event.value as f32 / 32767.0; |
| 674 | engine().input.set_gamepad_axis(idx, value); |
| 675 | } |
| 676 | } |
| 677 | } |
| 678 | } |
| 679 | |
| 680 | #[no_mangle] |
| 681 | pub extern "C" fn bloom_begin_drawing() { |
no test coverage detected