aboutsummaryrefslogtreecommitdiff
path: root/turtetris_master/usb_input.py
blob: d81c970ba655ba0c15b30619b1627daf1c89fdbd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import usb.core
import usb.backend.libusb1
import usb.util

# Personal Communication Systems, Inc. SNES Gamepad
CONF_SNES_GAMEPAD = {
    "idVendor": 0x0810,
    "idProduct": 0xe501,
    "iInterface": 0,
}


class Gamepad:
    "Simple gamepad handle function"

    def __init__(self, conf=CONF_SNES_GAMEPAD):
        "Initializes usb subsystem"
        backend = usb.backend.libusb1.get_backend(find_library=lambda x:
                                                  "/usr/lib/libusb-1.0.so")
        self.dev = usb.core.find(idVendor=conf['idVendor'],
                                 idProduct=conf['idProduct'],
                                 backend=backend)
        if self.dev is None:
            raise ValueError('Device not found')

        if self.dev.is_kernel_driver_active(conf['iInterface']) is True:
            # Detach any kernel driver so it won't interfere with us
            self.dev.detach_kernel_driver(conf['iInterface'])

        # set the active configuration. With no arguments, the first
        # configuration will be the active one
        self.dev.set_configuration()

        # get an endpoint instance
        self.cfg = self.dev.get_active_configuration()
        intf = self.cfg[(0, 0)]

        self.ep = usb.util.find_descriptor(
            intf,
            # match the first IN endpoint
            custom_match=lambda e:
            usb.util.endpoint_direction(e.bEndpointAddress) ==
            usb.util.ENDPOINT_IN
        )
        assert self.ep is not None

        self.state = {}
        for key in ['left', 'right', 'up', 'down']:
            self.state[key] = 0
        for key in ['select', 'start']:
            self.state[key] = False

    def check(self):
        "Check the input state"
        data = self.dev.read(self.ep.bEndpointAddress,
                             self.ep.wMaxPacketSize*2, 1000).tolist()
        new_state = {
            "left": data[3] < 120 or bool(data[5] & 0x80),
            "right": data[3] > 140 or bool(data[5] & 0x20),
            "up": data[4] < 120 or bool(data[5] & 0x10),
            "down": data[4] > 140 or bool(data[5] & 0x40),
            "select": bool(data[6] & 0x10),
            "start": bool(data[6] & 0x20),
        }
        changed = {}
        for key in ['left', 'right', 'up', 'down']:
            changed[key] = False
            if new_state[key]:
                if self.state[key] == 0 or self.state[key] > 14:
                    changed[key] = True
                    self.state[key] = 0
                self.state[key] += 1
            else:
                self.state[key] = 0
        for key in ['select', 'start']:
            changed[key] = new_state[key] and not self.state[key]
            self.state[key] = new_state[key]
        return changed