Verison 1.0.3 Release
Based on Buildbotics 0.4.14
This commit is contained in:
106
src/py/inevent/AbsAxisScaling.py
Normal file
106
src/py/inevent/AbsAxisScaling.py
Normal file
@@ -0,0 +1,106 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
# The inevent Python module was adapted from pi3d.event from the pi3d
|
||||
# project.
|
||||
#
|
||||
# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC.
|
||||
# Copyright (c) 2015, Tim Skillman.
|
||||
# Copyright (c) 2015, Paddy Gaunt.
|
||||
# Copyright (c) 2015, Tom Ritchford.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import array
|
||||
import fcntl
|
||||
import struct
|
||||
from inevent import ioctl
|
||||
|
||||
|
||||
def EVIOCGABS(axis):
|
||||
return ioctl._IOR(ord('E'), 0x40 + axis, "ffffff") # get abs value/limits
|
||||
|
||||
|
||||
|
||||
class AbsAxisScaling(object):
|
||||
"""
|
||||
Fetches and implements the EV_ABS axis scaling.
|
||||
|
||||
The constructor fetches the scaling values from the given stream for the
|
||||
given axis using an ioctl.
|
||||
|
||||
There is a scale method, which scales a given value to the range -1..+1.
|
||||
"""
|
||||
|
||||
def __init__(self, stream, axis):
|
||||
"""
|
||||
Fetch the scale values for this stream and fill in the instance
|
||||
variables accordingly.
|
||||
"""
|
||||
s = array.array("i", [1, 2, 3, 4, 5, 6])
|
||||
try:
|
||||
fcntl.ioctl(stream.filehandle, EVIOCGABS(axis), s)
|
||||
|
||||
except IOError:
|
||||
self.value = self.minimum = self.maximum = self.fuzz = self.flat = \
|
||||
self.resolution = 1
|
||||
|
||||
else:
|
||||
self.value, self.minimum, self.maximum, self.fuzz, self.flat, \
|
||||
self.resolution = struct.unpack("iiiiii", s)
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return "Value {0} Min {1}, Max {2}, Fuzz {3}, Flat {4}, Res {5}".format(
|
||||
self.value, self.minimum, self.maximum, self.fuzz, self.flat,
|
||||
self.resolution)
|
||||
|
||||
|
||||
def scale(self, value):
|
||||
"""
|
||||
scales the given value into the range -1..+1
|
||||
"""
|
||||
return (float(value) - float(self.minimum)) / \
|
||||
float(self.maximum - self.minimum) * 2.0 - 1.0
|
||||
124
src/py/inevent/Constants.py
Normal file
124
src/py/inevent/Constants.py
Normal file
@@ -0,0 +1,124 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
# The inevent Python module was adapted from pi3d.event from the pi3d
|
||||
# project.
|
||||
#
|
||||
# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC.
|
||||
# Copyright (c) 2015, Tim Skillman.
|
||||
# Copyright (c) 2015, Paddy Gaunt.
|
||||
# Copyright (c) 2015, Tom Ritchford.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
EV_SYN = 0x00
|
||||
EV_KEY = 0x01
|
||||
EV_REL = 0x02
|
||||
EV_ABS = 0x03
|
||||
EV_MSC = 0x04
|
||||
EV_SW = 0x05
|
||||
EV_LED = 0x11
|
||||
EV_SND = 0x12
|
||||
EV_REP = 0x14
|
||||
EV_FF = 0x15
|
||||
EV_PWR = 0x16
|
||||
EV_FF_STATUS = 0x17
|
||||
|
||||
ev_type_name = {}
|
||||
ev_type_name[EV_SYN] = "SYN"
|
||||
ev_type_name[EV_KEY] = "KEY"
|
||||
ev_type_name[EV_REL] = "REL"
|
||||
ev_type_name[EV_ABS] = "ABS"
|
||||
ev_type_name[EV_MSC] = "MSC"
|
||||
ev_type_name[EV_SW] = "SW"
|
||||
ev_type_name[EV_LED] = "LED"
|
||||
ev_type_name[EV_SND] = "SND"
|
||||
ev_type_name[EV_REP] = "REP"
|
||||
ev_type_name[EV_FF] = "FF"
|
||||
ev_type_name[EV_PWR] = "PWR"
|
||||
ev_type_name[EV_FF_STATUS] = "FF_STATUS"
|
||||
|
||||
SYN_REPORT = 0
|
||||
SYN_CONFIG = 1
|
||||
|
||||
REL_X = 0x00
|
||||
REL_Y = 0x01
|
||||
REL_Z = 0x02
|
||||
REL_RX = 0x03
|
||||
REL_RY = 0x04
|
||||
REL_RZ = 0x05
|
||||
REL_HWHEEL = 0x06
|
||||
REL_DIAL = 0x07
|
||||
REL_WHEEL = 0x08
|
||||
REL_MISC = 0x09
|
||||
REL_MAX = 0x0f
|
||||
|
||||
ABS_X = 0x00
|
||||
ABS_Y = 0x01
|
||||
ABS_Z = 0x02
|
||||
ABS_RX = 0x03
|
||||
ABS_RY = 0x04
|
||||
ABS_RZ = 0x05
|
||||
ABS_THROTTLE = 0x06
|
||||
ABS_RUDDER = 0x07
|
||||
ABS_WHEEL = 0x08
|
||||
ABS_GAS = 0x09
|
||||
ABS_BRAKE = 0x0a
|
||||
ABS_HAT0X = 0x10
|
||||
ABS_HAT0Y = 0x11
|
||||
ABS_HAT1X = 0x12
|
||||
ABS_HAT1Y = 0x13
|
||||
ABS_HAT2X = 0x14
|
||||
ABS_HAT2Y = 0x15
|
||||
ABS_HAT3X = 0x16
|
||||
ABS_HAT3Y = 0x17
|
||||
ABS_PRESSURE = 0x18
|
||||
ABS_DISTANCE = 0x19
|
||||
ABS_TILT_X = 0x1a
|
||||
ABS_TILT_Y = 0x1b
|
||||
ABS_TOOL_WIDTH = 0x1c
|
||||
ABS_VOLUME = 0x20
|
||||
ABS_MISC = 0x28
|
||||
ABS_MAX = 0x3f
|
||||
142
src/py/inevent/Event.py
Normal file
142
src/py/inevent/Event.py
Normal file
@@ -0,0 +1,142 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
# The inevent Python module was adapted from pi3d.event from the pi3d
|
||||
# project.
|
||||
#
|
||||
# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC.
|
||||
# Copyright (c) 2015, Tim Skillman.
|
||||
# Copyright (c) 2015, Paddy Gaunt.
|
||||
# Copyright (c) 2015, Tom Ritchford.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import struct
|
||||
|
||||
from inevent.Constants import *
|
||||
|
||||
|
||||
_format = 'llHHi'
|
||||
size = struct.calcsize(_format)
|
||||
|
||||
|
||||
class Event(object):
|
||||
"""
|
||||
A single event from the linux input event system.
|
||||
|
||||
Events are tuples: (Time, Type, Code, Value)
|
||||
In addition we remember the stream it came from.
|
||||
|
||||
Externally, only the unhandled event handler gets passed the whole event,
|
||||
but the SYN handler gets the code and value. (Also the keyboard handler, but
|
||||
those are renamed to key and value.)
|
||||
|
||||
This class is responsible for converting the Linux input event structure into
|
||||
one of these objects and back again.
|
||||
"""
|
||||
def __init__(self, stream, time = None, type = None, code = None,
|
||||
value = None):
|
||||
"""
|
||||
Create a new event.
|
||||
|
||||
Generally all but the stream parameter are left out; we will want to
|
||||
populate the object from a Linux input event using decode.
|
||||
"""
|
||||
self.stream = stream
|
||||
self.time = time
|
||||
self.type = type
|
||||
self.code = code
|
||||
self.value = value
|
||||
|
||||
|
||||
def get_type_name(self):
|
||||
if self.type not in ev_type_name: return '0x%x' % self.type
|
||||
return ev_type_name[self.type]
|
||||
|
||||
|
||||
def get_source(self):
|
||||
return "%s[%d]" % (self.stream.devType, self.stream.devIndex)
|
||||
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
Uses the stream to give the device type and whether it is currently grabbed.
|
||||
"""
|
||||
grabbed = "grabbed" if self.stream.grabbed else "ungrabbed"
|
||||
|
||||
return "Event %s %s @%f: %s 0x%x=0x%x" % (
|
||||
self.get_source(), grabbed, self.time, self.get_type_name(), self.code,
|
||||
self.value)
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "Event(%s, %f, 0x%x, 0x%x, 0x%x)" % (
|
||||
repr(self.stream), self.time, self.type, self.code, self.value)
|
||||
|
||||
|
||||
def encode(self):
|
||||
"""
|
||||
Encode this event into a Linux input event structure.
|
||||
|
||||
The output is packed into a string. It is unlikely that this function
|
||||
will be required, but it might as well be here.
|
||||
"""
|
||||
tsec = int(self.time)
|
||||
tfrac = int((self.time - tsec) * 1000000)
|
||||
|
||||
return struct.pack(_format, tsec, tfrac, self.type, self.code, self.value)
|
||||
|
||||
|
||||
def decode(self, s):
|
||||
"""
|
||||
Decode a Linux input event into the fields of this object.
|
||||
|
||||
Arguments:
|
||||
*s*
|
||||
A binary structure packed into a string.
|
||||
"""
|
||||
tsec, tfrac, self.type, self.code, self.value = struct.unpack(_format, s)
|
||||
|
||||
self.time = tsec + tfrac / 1000000.0
|
||||
146
src/py/inevent/EventHandler.py
Normal file
146
src/py/inevent/EventHandler.py
Normal file
@@ -0,0 +1,146 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
# The inevent Python module was adapted from pi3d.event from the pi3d
|
||||
# project.
|
||||
#
|
||||
# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC.
|
||||
# Copyright (c) 2015, Tim Skillman.
|
||||
# Copyright (c) 2015, Paddy Gaunt.
|
||||
# Copyright (c) 2015, Tom Ritchford.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from inevent.Constants import *
|
||||
from inevent.EventStream import EventStream
|
||||
|
||||
|
||||
class EventHandler(object):
|
||||
"""
|
||||
A class to handle events.
|
||||
|
||||
Four types of events are handled: REL (mouse movement), KEY (keybaord keys and
|
||||
other device buttons), ABS (joysticks and gamepad analogue sticks) and SYN
|
||||
(delimits simultaneous events such as mouse movements)
|
||||
"""
|
||||
def __init__(self):
|
||||
self.buttons = dict()
|
||||
|
||||
|
||||
def event(self, event, handler, name):
|
||||
"""
|
||||
Handles the given event.
|
||||
|
||||
If the event is passed to a handler or otherwise handled then returns None,
|
||||
else returns the event. All handlers are optional.
|
||||
|
||||
All key events are handled by putting them in the self.buttons dict, and
|
||||
optionally by calling the supplied handler.
|
||||
|
||||
REL X, Y and wheel V and H events are all accumulated internally and
|
||||
also optionally passed to the supplied handler. All these events are
|
||||
handled.
|
||||
|
||||
ABS X, Y, Z, RX, RY, RZ, Hat0X, Hat0Y are all accumulated internally and
|
||||
also optionally passed to the supplied handler. Other ABS events are not
|
||||
handled.
|
||||
|
||||
All SYN events are passed to the supplied handler.
|
||||
|
||||
There are several ABS events that we do not handle. In particular:
|
||||
THROTTLE, RUDDER, WHEEL, GAS, BRAKE, HAT1, HAT2, HAT3, PRESSURE,
|
||||
DISTANCE, TILT, TOOL_WIDTH. Implementing these is left as an exercise
|
||||
for the interested reader.
|
||||
|
||||
Likewise, since one handler is handling all events for all devices, we
|
||||
may get the situation where two devices return the same button. The only
|
||||
way to handle that would seem to be to have a key dict for every device,
|
||||
which seems needlessly profligate for a situation that may never arise.
|
||||
"""
|
||||
|
||||
state = event.stream.state
|
||||
|
||||
if event.type == EV_KEY: self.buttons[event.code] = event.value
|
||||
elif event.type == EV_REL: state.rel[event.code] += event.value
|
||||
elif event.type == EV_ABS:
|
||||
state.abs[event.code] = event.stream.scale(event.code, event.value)
|
||||
|
||||
if handler: handler.event(event, state, name)
|
||||
|
||||
|
||||
def key_state(self, code):
|
||||
"""
|
||||
Returns the last event value for the given key code.
|
||||
|
||||
Key names can be converted to key codes using codeOf[str].
|
||||
If the key is pressed the returned value will be 1 (pressed) or 2 (held).
|
||||
If the key is not pressed, the returned value will be 0.
|
||||
"""
|
||||
return self.buttons.get(code, 0)
|
||||
|
||||
|
||||
def clear_key(self, code):
|
||||
"""
|
||||
Clears the event value for the given key code.
|
||||
|
||||
Key names can be converted to key codes using codeOf[str].
|
||||
This emulates a key-up but does not generate any events.
|
||||
"""
|
||||
self.buttons[code] = 0
|
||||
|
||||
|
||||
def get_keys(self):
|
||||
"""
|
||||
Returns the first of whichever keys have been pressed.
|
||||
|
||||
Key names can be converted to key codes using codeOf[str].
|
||||
This emulates a key-up but does not generate any events.
|
||||
"""
|
||||
k_list = []
|
||||
|
||||
for k in self.buttons:
|
||||
if self.buttons[k] != 0: k_list.append(k)
|
||||
|
||||
return k_list
|
||||
145
src/py/inevent/EventState.py
Normal file
145
src/py/inevent/EventState.py
Normal file
@@ -0,0 +1,145 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
# The inevent Python module was adapted from pi3d.event from the pi3d
|
||||
# project.
|
||||
#
|
||||
# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC.
|
||||
# Copyright (c) 2015, Tim Skillman.
|
||||
# Copyright (c) 2015, Paddy Gaunt.
|
||||
# Copyright (c) 2015, Tom Ritchford.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from inevent.Constants import *
|
||||
|
||||
|
||||
class EventState:
|
||||
def __init__(self):
|
||||
self.abs = [0.0] * ABS_MAX
|
||||
self.rel = [0.0] * REL_MAX
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return ("({:6.3f}, {:6.3f}, {:6.3f}) ".format(*self.get_joystick3d()) +
|
||||
"({:6.3f}, {:6.3f}, {:6.3f}) ".format(*self.get_joystickR3d()) +
|
||||
"({:2.0f}, {:2.0f}) ".format(*self.get_hat()) +
|
||||
"({:0.2f}, {:0.2f}) ".format(*self.get_mouse()) +
|
||||
"({:0.2f}, {:0.2f})".format(*self.get_wheel()))
|
||||
|
||||
|
||||
def get_joystick(self):
|
||||
"""
|
||||
Returns the x,y coordinates for a joystick or left gamepad analogue stick.
|
||||
|
||||
The values are returned as a tuple. All values are -1.0 to +1.0 with
|
||||
0.0 being centred.
|
||||
"""
|
||||
return self.abs[ABS_X], self.abs[ABS_Y]
|
||||
|
||||
|
||||
def get_joystick3d(self):
|
||||
"""
|
||||
Returns the x,y,z coordinates for a joystick or left gamepad analogue stick
|
||||
|
||||
The values are returned as a tuple. All values are -1.0 to +1.0 with
|
||||
0.0 being centred.
|
||||
"""
|
||||
return self.abs[ABS_X], self.abs[ABS_Y], self.abs[ABS_Z]
|
||||
|
||||
|
||||
def get_joystickR(self):
|
||||
"""
|
||||
Returns the x,y coordinates for a right gamepad analogue stick.
|
||||
|
||||
The values are returned as a tuple. For some odd reason, the gamepad
|
||||
returns values in the Z axes of both joysticks, with y being the first.
|
||||
|
||||
All values are -1.0 to +1.0 with 0.0 being centred.
|
||||
"""
|
||||
return self.abs[ABS_RZ], self.abs[ABS_Z]
|
||||
|
||||
|
||||
def get_joystickR3d(self):
|
||||
"""
|
||||
Returns the x,y,z coordinates for a 2nd joystick control
|
||||
|
||||
The values are returned as a tuple. All values are -1.0 to +1.0 with
|
||||
0.0 being centred.
|
||||
"""
|
||||
return self.abs[ABS_RX], self.abs[ABS_RY], self.abs[ABS_RZ]
|
||||
|
||||
|
||||
def get_hat(self):
|
||||
"""
|
||||
Returns the x,y coordinates for a joystick hat or gamepad direction pad
|
||||
|
||||
The values are returned as a tuple. All values are -1.0 to +1.0 with
|
||||
0.0 being centred.
|
||||
"""
|
||||
return self.abs[ABS_HAT0X], self.abs[ABS_HAT0Y]
|
||||
|
||||
|
||||
def get_mouse(self):
|
||||
return self.rel[REL_X], self.rel[REL_Y]
|
||||
|
||||
|
||||
def get_wheel(self):
|
||||
return self.rel[REL_WHEEL], self.rel[REL_HWHEEL]
|
||||
|
||||
|
||||
def get_mouse_movement(self):
|
||||
"""
|
||||
Returns the accumulated REL (mouse or other relative device) movements
|
||||
since the last call.
|
||||
|
||||
The returned value is a tuple: (X, Y, WHEEL, H-WHEEL)
|
||||
"""
|
||||
ret = self.get_mouse() + self.get_wheel()
|
||||
|
||||
self.rel[REL_X] = self.rel[REL_Y] = 0
|
||||
self.rel[REL_WHEEL] = self.rel[REL_HWHEEL] = 0
|
||||
|
||||
return ret
|
||||
218
src/py/inevent/EventStream.py
Normal file
218
src/py/inevent/EventStream.py
Normal file
@@ -0,0 +1,218 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
# The inevent Python module was adapted from pi3d.event from the pi3d
|
||||
# project.
|
||||
#
|
||||
# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC.
|
||||
# Copyright (c) 2015, Tim Skillman.
|
||||
# Copyright (c) 2015, Paddy Gaunt.
|
||||
# Copyright (c) 2015, Tom Ritchford.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import fcntl
|
||||
import os
|
||||
import select
|
||||
import logging
|
||||
|
||||
from inevent.Constants import *
|
||||
from inevent import ioctl
|
||||
from inevent.AbsAxisScaling import AbsAxisScaling
|
||||
from inevent import Event
|
||||
from inevent.EventState import EventState
|
||||
|
||||
|
||||
log = logging.getLogger('inevent')
|
||||
|
||||
EVIOCGRAB = ioctl._IOW(ord('E'), 0x90, "i") # Grab/Release device
|
||||
|
||||
|
||||
|
||||
class EventStream(object):
|
||||
"""
|
||||
encapsulates the event* file handling
|
||||
|
||||
Each device is represented by a file in /dev/input called eventN, where N is
|
||||
a small number. (Actually, a keybaord can be represented by two such files.)
|
||||
Instances of this class open one of these files and provide means to read
|
||||
events from them.
|
||||
|
||||
Class methods also exist to read from multiple files simultaneously, and
|
||||
also to grab and ungrab all instances of a given type.
|
||||
"""
|
||||
axisX = 0
|
||||
axisY = 1
|
||||
axisZ = 2
|
||||
axisRX = 3
|
||||
axisRY = 4
|
||||
axisRZ = 5
|
||||
axisHat0X = 6
|
||||
axisHat0Y = 7
|
||||
axisHat1X = 8
|
||||
axisHat1Y = 9
|
||||
axisHat2X = 10
|
||||
axisHat2Y = 11
|
||||
axisHat3X = 12
|
||||
axisHat3Y = 13
|
||||
axisThrottle = 14
|
||||
axisRudder = 15
|
||||
axisWheel = 16
|
||||
axisGas = 17
|
||||
axisBrake = 18
|
||||
axisPressure = 19
|
||||
axisDistance = 20
|
||||
axisTiltX = 21
|
||||
axisTiltY = 22
|
||||
axisToolWidth = 23
|
||||
numAxes = 24
|
||||
|
||||
axisToEvent = [
|
||||
ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ, ABS_HAT0X, ABS_HAT0Y,
|
||||
ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y, ABS_HAT3X, ABS_HAT3Y,
|
||||
ABS_THROTTLE, ABS_RUDDER, ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_PRESSURE,
|
||||
ABS_DISTANCE, ABS_TILT_X, ABS_TILT_Y, ABS_TOOL_WIDTH]
|
||||
|
||||
|
||||
def __init__(self, devIndex, devType, devName):
|
||||
"""
|
||||
Opens the given /dev/input/event file and grabs it.
|
||||
|
||||
Also adds it to a class-global list of all existing streams.
|
||||
"""
|
||||
self.devIndex = devIndex
|
||||
self.devType = devType
|
||||
self.devName = devName
|
||||
self.filename = "/dev/input/event" + str(devIndex)
|
||||
self.filehandle = os.open(self.filename, os.O_RDWR)
|
||||
self.state = EventState()
|
||||
self.grab(True)
|
||||
self.absInfo = [None] * ABS_MAX
|
||||
|
||||
if devType == "js":
|
||||
for axis in range(ABS_MAX):
|
||||
self.absInfo[axis] = AbsAxisScaling(self, axis)
|
||||
|
||||
|
||||
def scale(self, axis, value):
|
||||
"""
|
||||
Scale the given value according to the given axis.
|
||||
|
||||
acquire_abs_info must have been previously called to acquire the data to
|
||||
do the scaling.
|
||||
"""
|
||||
assert axis < ABS_MAX, "Axis number out of range"
|
||||
|
||||
if self.absInfo[axis]: return self.absInfo[axis].scale(value)
|
||||
else: return value
|
||||
|
||||
|
||||
def grab(self, grab = True):
|
||||
"""
|
||||
Grab (or release) exclusive access to all devices of the given type.
|
||||
|
||||
The devices are grabbed if grab is True and released if grab is False.
|
||||
|
||||
All devices are grabbed to begin with. We might want to ungrab the
|
||||
keyboard for example to use it for text entry. While not grabbed, all
|
||||
key-down and key-hold events are filtered out.
|
||||
"""
|
||||
fcntl.ioctl(self.filehandle, EVIOCGRAB, 1 if grab else 0)
|
||||
self.grabbed = grab
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
"""s
|
||||
Required to make this class an iterator
|
||||
"""
|
||||
return self
|
||||
|
||||
|
||||
def next(self): return self.__next__()
|
||||
|
||||
|
||||
def __next__(self):
|
||||
"""
|
||||
Returns the next waiting event.
|
||||
|
||||
If no event is waiting, returns None.
|
||||
"""
|
||||
ready = select.select([self.filehandle], [], [], 0)[0]
|
||||
if ready: return self.read()
|
||||
|
||||
|
||||
def read(self):
|
||||
"""
|
||||
Read and return the next waiting event.
|
||||
"""
|
||||
try:
|
||||
s = os.read(self.filehandle, Event.size)
|
||||
if s:
|
||||
event = Event.Event(self)
|
||||
event.decode(s)
|
||||
return event
|
||||
|
||||
except Exception as e:
|
||||
log.info('Reading event: %s' % e)
|
||||
|
||||
|
||||
def __enter__(self): return self
|
||||
|
||||
|
||||
def release(self):
|
||||
"Ungrabs the file and closes it."
|
||||
|
||||
try:
|
||||
self.grab(False)
|
||||
os.close(self.filehandle)
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
"Ungrabs the file and closes it."
|
||||
|
||||
self.release()
|
||||
245
src/py/inevent/FindDevices.py
Normal file
245
src/py/inevent/FindDevices.py
Normal file
@@ -0,0 +1,245 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
# The inevent Python module was adapted from pi3d.event from the pi3d
|
||||
# project.
|
||||
#
|
||||
# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC.
|
||||
# Copyright (c) 2015, Tim Skillman.
|
||||
# Copyright (c) 2015, Paddy Gaunt.
|
||||
# Copyright (c) 2015, Tom Ritchford.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import re
|
||||
import logging
|
||||
from inevent.Constants import *
|
||||
|
||||
log = logging.getLogger('inevent')
|
||||
|
||||
|
||||
def test_bit(nlst, b):
|
||||
index = b / 32
|
||||
bit = b % 32
|
||||
return index < len(nlst) and nlst[index] & (1 << bit)
|
||||
|
||||
|
||||
def EvToStr(events):
|
||||
s = []
|
||||
|
||||
if test_bit(events, EV_SYN): s.append("EV_SYN")
|
||||
if test_bit(events, EV_KEY): s.append("EV_KEY")
|
||||
if test_bit(events, EV_REL): s.append("EV_REL")
|
||||
if test_bit(events, EV_ABS): s.append("EV_ABS")
|
||||
if test_bit(events, EV_MSC): s.append("EV_MSC")
|
||||
if test_bit(events, EV_LED): s.append("EV_LED")
|
||||
if test_bit(events, EV_SND): s.append("EV_SND")
|
||||
if test_bit(events, EV_REP): s.append("EV_REP")
|
||||
if test_bit(events, EV_FF): s.append("EV_FF" )
|
||||
if test_bit(events, EV_PWR): s.append("EV_PWR")
|
||||
if test_bit(events, EV_FF_STATUS): s.append("EV_FF_STATUS")
|
||||
|
||||
return s
|
||||
|
||||
|
||||
class DeviceCapabilities(object):
|
||||
def __init__(self, firstLine, filehandle):
|
||||
self.EV_SYNevents = []
|
||||
self.EV_KEYevents = []
|
||||
self.EV_RELevents = []
|
||||
self.EV_ABSevents = []
|
||||
self.EV_MSCevents = []
|
||||
self.EV_LEDevents = []
|
||||
self.EV_SNDevents = []
|
||||
self.EV_REPevents = []
|
||||
self.EV_FFevents = []
|
||||
self.EV_PWRevents = []
|
||||
self.EV_FF_STATUSevents = []
|
||||
self.eventTypes = []
|
||||
|
||||
match = re.search(".*Bus=([0-9A-Fa-f]+).*Vendor=([0-9A-Fa-f]+).*"
|
||||
"Product=([0-9A-Fa-f]+).*Version=([0-9A-Fa-f]+).*",
|
||||
firstLine)
|
||||
|
||||
if not match:
|
||||
log.warning("Do not understand device ID: %s", firstLine)
|
||||
self.bus = 0
|
||||
self.vendor = 0
|
||||
self.product = 0
|
||||
self.version = 0
|
||||
|
||||
else:
|
||||
self.bus = int(match.group(1), base = 16)
|
||||
self.vendor = int(match.group(2), base = 16)
|
||||
self.product = int(match.group(3), base = 16)
|
||||
self.version = int(match.group(4), base = 16)
|
||||
|
||||
for line in filehandle:
|
||||
if not line.strip(): break
|
||||
|
||||
if line[0] == "N":
|
||||
match = re.search('Name="([^"]+)"', line)
|
||||
if match: self.name = match.group(1)
|
||||
else: self.name = "UNKNOWN"
|
||||
|
||||
elif line[0] == "P":
|
||||
match = re.search('Phys=(.+)', line)
|
||||
if match: self.phys = match.group(1)
|
||||
else: self.phys = "UNKNOWN"
|
||||
|
||||
elif line[0] == "S":
|
||||
match = re.search('Sysfs=(.+)', line)
|
||||
if match: self.sysfs = match.group(1)
|
||||
else: self.sysfs = "UNKNOWN"
|
||||
|
||||
elif line[0] == "U":
|
||||
match = re.search('Uniq=(.*)', line)
|
||||
if match: self.uniq = match.group(1)
|
||||
else: self.uniq = "UNKNOWN"
|
||||
|
||||
elif line[0] == "H":
|
||||
match = re.search('Handlers=(.+)', line)
|
||||
if match: self.handlers = match.group(1).split()
|
||||
else: self.handlers = []
|
||||
|
||||
elif line[:5] == "B: EV":
|
||||
eventsNums = [int(x, base = 16) for x in line[6:].split()]
|
||||
eventsNums.reverse()
|
||||
self.eventTypes = eventsNums
|
||||
|
||||
elif line[:6] == "B: KEY":
|
||||
eventsNums = [int(x, base = 16) for x in line[7:].split()]
|
||||
eventsNums.reverse()
|
||||
self.EV_KEYevents = eventsNums
|
||||
|
||||
elif line[:6] == "B: ABS":
|
||||
eventsNums = [int(x, base = 16) for x in line[7:].split()]
|
||||
eventsNums.reverse()
|
||||
self.EV_ABSevents = eventsNums
|
||||
|
||||
elif line[:6] == "B: MSC":
|
||||
eventsNums = [int(x, base = 16) for x in line[7:].split()]
|
||||
eventsNums.reverse()
|
||||
self.EV_MSCevents = eventsNums
|
||||
|
||||
elif line[:6] == "B: REL":
|
||||
eventsNums = [int(x, base = 16) for x in line[7:].split()]
|
||||
eventsNums.reverse()
|
||||
self.EV_RELevents = eventsNums
|
||||
|
||||
elif line[:6] == "B: LED":
|
||||
eventsNums = [int(x, base = 16) for x in line[7:].split()]
|
||||
eventsNums.reverse()
|
||||
self.EV_LEDevents = eventsNums
|
||||
|
||||
for handler in self.handlers:
|
||||
if handler[:5] == "event": self.eventIndex = int(handler[5:])
|
||||
|
||||
self.isMouse = False
|
||||
self.isKeyboard = False
|
||||
self.isJoystick = False
|
||||
|
||||
|
||||
def doesProduce(self, eventType, eventCode):
|
||||
return test_bit(self.eventTypes, eventType) and (
|
||||
(eventType == EV_SYN and test_bit(self.EV_SYNevents, eventCode)) or
|
||||
(eventType == EV_KEY and test_bit(self.EV_KEYevents, eventCode)) or
|
||||
(eventType == EV_REL and test_bit(self.EV_RELevents, eventCode)) or
|
||||
(eventType == EV_ABS and test_bit(self.EV_ABSevents, eventCode)) or
|
||||
(eventType == EV_MSC and test_bit(self.EV_MSCevents, eventCode)) or
|
||||
(eventType == EV_LED and test_bit(self.EV_LEDevents, eventCode)) or
|
||||
(eventType == EV_SND and test_bit(self.EV_SNDevents, eventCode)) or
|
||||
(eventType == EV_REP and test_bit(self.EV_REPevents, eventCode)) or
|
||||
(eventType == EV_FF and test_bit(self.EV_FFevents, eventCode)) or
|
||||
(eventType == EV_PWR and test_bit(self.EV_PWRevents, eventCode)) or
|
||||
(eventType == EV_FF_STATUS and
|
||||
test_bit(self.EV_FF_STATUSevents, eventCode)))
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return (
|
||||
("%s\n"
|
||||
"Bus: %s Vendor: %s Product: %s Version: %s\n"
|
||||
"Phys: %s\n"
|
||||
"Sysfs: %s\n"
|
||||
"Uniq: %s\n"
|
||||
"Handlers: %s Event Index: %s\n"
|
||||
"Keyboard: %s Mouse: %s Joystick: %s\n"
|
||||
"Events: %s") % (
|
||||
self.name, self.bus, self.vendor, self.product, self.version, self.phys,
|
||||
self.sysfs, self.uniq, self.handlers, self.eventIndex, self.isKeyboard,
|
||||
self.isMouse, self.isJoystick, EvToStr(self.eventTypes)))
|
||||
|
||||
|
||||
deviceCapabilities = []
|
||||
|
||||
|
||||
def get_devices(filename = "/proc/bus/input/devices"):
|
||||
global deviceCapabilities
|
||||
|
||||
with open("/proc/bus/input/devices", "r") as filehandle:
|
||||
for line in filehandle:
|
||||
if line[0] == "I":
|
||||
deviceCapabilities.append(DeviceCapabilities(line, filehandle))
|
||||
|
||||
return deviceCapabilities
|
||||
|
||||
|
||||
def print_devices():
|
||||
devs = get_devices()
|
||||
|
||||
for dev in devs:
|
||||
print(str(dev))
|
||||
print(" ABS: {}"
|
||||
.format([x for x in range(64) if test_bit(dev.EV_ABSevents, x)]))
|
||||
print(" REL: {}"
|
||||
.format([x for x in range(64) if test_bit(dev.EV_RELevents, x)]))
|
||||
print(" MSC: {}"
|
||||
.format([x for x in range(64) if test_bit(dev.EV_MSCevents, x)]))
|
||||
print(" KEY: {}"
|
||||
.format([x for x in range(512) if test_bit(dev.EV_KEYevents, x)]))
|
||||
print(" LED: {}"
|
||||
.format([x for x in range(64) if test_bit(dev.EV_LEDevents, x)]))
|
||||
print()
|
||||
288
src/py/inevent/InEvent.py
Normal file
288
src/py/inevent/InEvent.py
Normal file
@@ -0,0 +1,288 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
# The inevent Python module was adapted from pi3d.event from the pi3d
|
||||
# project.
|
||||
#
|
||||
# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC.
|
||||
# Copyright (c) 2015, Tim Skillman.
|
||||
# Copyright (c) 2015, Paddy Gaunt.
|
||||
# Copyright (c) 2015, Tom Ritchford.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import pyudev
|
||||
import re
|
||||
import select
|
||||
import errno
|
||||
import functools
|
||||
import logging
|
||||
|
||||
from inevent.EventHandler import EventHandler
|
||||
from inevent import Keys
|
||||
from inevent.Constants import *
|
||||
from inevent.EventStream import EventStream
|
||||
|
||||
|
||||
log = logging.getLogger('inevent')
|
||||
|
||||
_KEYS = (k for k in vars(Keys) if not k.startswith('_'))
|
||||
KEY_CODE = dict((k, getattr(Keys, k)) for k in _KEYS)
|
||||
CODE_KEY = {}
|
||||
for v in KEY_CODE: CODE_KEY[KEY_CODE[v]] = v
|
||||
|
||||
|
||||
def key_to_code(key):
|
||||
return KEY_CODE.get(str(key), -1) \
|
||||
if isinstance(key, str) else key
|
||||
|
||||
|
||||
def code_to_key(code): return CODE_KEY.get(code, '')
|
||||
|
||||
|
||||
class InEvent(object):
|
||||
"""Encapsulates the entire InEvent subsystem.
|
||||
|
||||
This is generally all you need to import.
|
||||
|
||||
On instantiation, we open all devices that are keyboards, mice or joysticks.
|
||||
That means we might have two of one sort of another, and that might be a
|
||||
problem, but it would be rather rare.
|
||||
|
||||
There are several ABS (joystick, touch) events that we do not handle,
|
||||
specifically THROTTLE, RUDDER, WHEEL, GAS, BRAKE, HAT1, HAT2, HAT3, PRESSURE,
|
||||
DISTANCE, TILT, TOOL_WIDTH. Implementing these is left as an exercise
|
||||
for the interested reader. Similarly, we make no attempt to handle
|
||||
multi-touch.
|
||||
|
||||
Handlers can be supplied, in which case they are called for each event, but
|
||||
it isn't necessary; API exists for all the events.
|
||||
|
||||
The handler signature is:
|
||||
|
||||
def handler_func(event, state)
|
||||
|
||||
where:
|
||||
event:
|
||||
An Event object describing the event.
|
||||
|
||||
state:
|
||||
An EventState object describing the current state.
|
||||
|
||||
Use key_to_code() to convert from the name of a key to its code,
|
||||
and code_to_key() to convert a code to a name.
|
||||
|
||||
The keys are listed in inevent.Constants.py or /usr/include/linux/input.h
|
||||
Note that the key names refer to a US keyboard.
|
||||
"""
|
||||
def __init__(self, ioloop, cb, types = 'kbd mouse js'.split()):
|
||||
self.ioloop = ioloop
|
||||
self.cb = cb
|
||||
self.streams = []
|
||||
self.handler = EventHandler()
|
||||
self.types = types
|
||||
|
||||
self.udevCtx = pyudev.Context()
|
||||
self.udevMon = pyudev.Monitor.from_netlink(self.udevCtx)
|
||||
self.udevMon.filter_by(subsystem = 'input')
|
||||
|
||||
devs = list(self.find_devices(types))
|
||||
for index, type, name in devs:
|
||||
self.add_stream(index, type, name)
|
||||
|
||||
self.udevMon.start()
|
||||
ioloop.add_handler(self.udevMon.fileno(), self.udev_handler, ioloop.READ)
|
||||
|
||||
|
||||
def get_dev(self, index):
|
||||
return pyudev.Device.from_name(self.udevCtx, 'input', 'event%s' % index)
|
||||
|
||||
|
||||
def get_dev_name(self, index):
|
||||
try:
|
||||
dev = self.get_dev(index)
|
||||
return dev.parent.attributes.asstring('name').decode('utf-8')
|
||||
except: pass
|
||||
|
||||
|
||||
def find_devices(self, types):
|
||||
"""Finds the event indices of all devices of the specified types.
|
||||
|
||||
A type is a string on the handlers line of /proc/bus/input/devices.
|
||||
Keyboards use "kbd", mice use "mouse" and joysticks (and gamepads) use "js".
|
||||
|
||||
Returns a list of integer indexes N, where /dev/input/eventN is the event
|
||||
stream for each device.
|
||||
|
||||
If butNot is given it holds a list of tuples which the returned values
|
||||
should not match.
|
||||
|
||||
All devices of each type are returned; if you have two mice, they will both
|
||||
be used.
|
||||
"""
|
||||
with open("/proc/bus/input/devices", "r") as filehandle:
|
||||
for line in filehandle:
|
||||
if line[0] == "H":
|
||||
for type in types:
|
||||
if type in line:
|
||||
match = re.search("event([0-9]+)", line)
|
||||
index = match and match.group(1)
|
||||
if index:
|
||||
yield int(index), type, self.get_dev_name(index)
|
||||
break
|
||||
|
||||
|
||||
def process_udev_event(self):
|
||||
action, device = self.udevMon.receive_device()
|
||||
if device is None: return
|
||||
|
||||
match = re.search(r"/dev/input/event([0-9]+)", str(device.device_node))
|
||||
devIndex = match and match.group(1)
|
||||
if not devIndex: return
|
||||
devIndex = int(devIndex)
|
||||
|
||||
if action == 'add':
|
||||
for index, devType, devName in self.find_devices(self.types):
|
||||
if index == devIndex:
|
||||
self.add_stream(devIndex, devType, devName)
|
||||
break
|
||||
|
||||
if action == 'remove': self.remove_stream(devIndex)
|
||||
|
||||
|
||||
def stream_handler(self, fd, events):
|
||||
for stream in self.streams:
|
||||
if stream.filehandle == fd:
|
||||
while True:
|
||||
event = stream.next()
|
||||
if event: self.handler.event(event, self.cb, stream.devName)
|
||||
else: break
|
||||
|
||||
|
||||
def udev_handler(self, fd, events):
|
||||
self.process_udev_event()
|
||||
|
||||
|
||||
def add_stream(self, devIndex, devType, devName):
|
||||
try:
|
||||
stream = EventStream(devIndex, devType, devName)
|
||||
self.streams.append(stream)
|
||||
|
||||
self.ioloop.add_handler(stream.filehandle, self.stream_handler,
|
||||
self.ioloop.READ)
|
||||
|
||||
log.info('Added %s[%d] %s', devType, devIndex, devName)
|
||||
|
||||
except OSError as e:
|
||||
log.warning('Failed to add %s[%d]: %s', devType, devIndex, e)
|
||||
|
||||
|
||||
def remove_stream(self, devIndex):
|
||||
for stream in self.streams:
|
||||
if stream.devIndex == devIndex:
|
||||
self.streams.remove(stream)
|
||||
self.ioloop.remove_handler(stream.filehandle)
|
||||
stream.release()
|
||||
self.cb.clear()
|
||||
|
||||
log.info('Removed %s[%d]', stream.devType, devIndex)
|
||||
|
||||
|
||||
def key_state(self, key):
|
||||
"""
|
||||
Returns the state of the given key.
|
||||
|
||||
The returned value will be 0 for key-up, or 1 for key-down. This method
|
||||
returns a key-held(2) as 1 to aid in using the returned value as a
|
||||
movement distance.
|
||||
|
||||
This function accepts either the key code or the string name of the key.
|
||||
It would be more efficient to look-up and store the code of
|
||||
the key with KEY_CODE[], rather than using the string every time. (Which
|
||||
involves a dict look-up keyed with a string for every key_state call, every
|
||||
time around the loop.)
|
||||
|
||||
Gamepad keys are:
|
||||
Select = BTN_BASE3, Start = BTN_BASE4
|
||||
L1 = BTN_TOP R1 = BTN_BASE
|
||||
L2 = BTN_PINKIE R2 = BTN_BASE2
|
||||
|
||||
The action buttons are:
|
||||
BTN_THUMB
|
||||
BTN_TRIGGER
|
||||
BTN_TOP
|
||||
BTN_THUMB2
|
||||
|
||||
Analogue Left Button = BTN_BASE5
|
||||
Analogue Right Button = BTN_BASE6
|
||||
|
||||
Some of those may clash with extended mouse buttons, so if you are using
|
||||
both at once, you'll see some overlap.
|
||||
|
||||
The direction pad is hat0 (see get_hat)
|
||||
"""
|
||||
return self.handler.key_state(key_to_code(key))
|
||||
|
||||
|
||||
def clear_key(self, key):
|
||||
"""
|
||||
Clears the state of the given key.
|
||||
|
||||
Emulates a key-up, but does not call any handlers.
|
||||
"""
|
||||
return self.handler.clear_key(key_to_code(key))
|
||||
|
||||
|
||||
def get_keys(self):
|
||||
return [code_to_key(k) for k in self.handler.get_keys()]
|
||||
|
||||
|
||||
def release(self):
|
||||
"""
|
||||
Ungrabs all streams and closes all files.
|
||||
|
||||
Only do this when you're finished with this object. You can't use it again.
|
||||
"""
|
||||
for s in self.streams: s.release()
|
||||
153
src/py/inevent/JogHandler.py
Normal file
153
src/py/inevent/JogHandler.py
Normal file
@@ -0,0 +1,153 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
import logging
|
||||
|
||||
from inevent.Constants import *
|
||||
|
||||
|
||||
log = logging.getLogger('inevent')
|
||||
log.setLevel(logging.INFO)
|
||||
|
||||
|
||||
def axes_to_string(axes):
|
||||
s = ''
|
||||
for axis in axes:
|
||||
if s: s += ', '
|
||||
else: s = '('
|
||||
s += '{:6.3f}'.format(axis)
|
||||
return s + ')'
|
||||
|
||||
|
||||
def event_to_string(event, state):
|
||||
s = '{} {}: '.format(event.get_source(), event.get_type_name())
|
||||
|
||||
if event.type == EV_ABS:
|
||||
s += axes_to_string(state.get_joystick3d()) + ' ' + \
|
||||
axes_to_string(state.get_joystickR3d()) + ' ' + \
|
||||
'({:2.0f}, {:2.0f}) '.format(*state.get_hat())
|
||||
|
||||
if event.type == EV_REL:
|
||||
s += '({:d}, {:d}) '.format(*state.get_mouse()) + \
|
||||
'({:d}, {:d})'.format(*state.get_wheel())
|
||||
|
||||
if event.type == EV_KEY:
|
||||
state = 'pressed' if event.value else 'released'
|
||||
s += '0x{:x} {}'.format(event.code, state)
|
||||
|
||||
return s
|
||||
|
||||
|
||||
class JogHandler:
|
||||
def __init__(self, config):
|
||||
self.config = config
|
||||
self.reset()
|
||||
|
||||
|
||||
def changed(self):
|
||||
log.info(axes_to_string(self.axes) + ' x {:d}'.format(self.speed))
|
||||
|
||||
|
||||
def up(self): log.debug('up')
|
||||
def down(self): log.debug('down')
|
||||
def left(self): log.debug('left')
|
||||
def right(self): log.debug('right')
|
||||
|
||||
|
||||
def reset(self):
|
||||
self.axes = [0.0, 0.0, 0.0, 0.0]
|
||||
self.speed = 3
|
||||
self.vertical_lock = 0
|
||||
self.horizontal_lock = 0
|
||||
|
||||
|
||||
def clear(self):
|
||||
self.reset()
|
||||
self.changed()
|
||||
|
||||
|
||||
def get_config(self, name):
|
||||
if name in self.config: return self.config[name]
|
||||
return self.config['default']
|
||||
|
||||
|
||||
def event(self, event, state, dev_name):
|
||||
if event.type not in [EV_ABS, EV_REL, EV_KEY]: return
|
||||
|
||||
config = self.get_config(dev_name)
|
||||
changed = False
|
||||
|
||||
# Process event
|
||||
if event.type == EV_ABS and event.code in config['axes']:
|
||||
pass
|
||||
|
||||
elif event.type == EV_ABS and event.code in config['arrows']:
|
||||
axis = config['arrows'].index(event.code)
|
||||
|
||||
if event.value < 0:
|
||||
if axis == 1: self.up()
|
||||
else: self.left()
|
||||
|
||||
elif 0 < event.value:
|
||||
if axis == 1: self.down()
|
||||
else: self.right()
|
||||
|
||||
elif event.type == EV_KEY and event.code in config['speed']:
|
||||
old_speed = self.speed
|
||||
self.speed = config['speed'].index(event.code) + 1
|
||||
if self.speed != old_speed: changed = True
|
||||
|
||||
elif event.type == EV_KEY and event.code in config['lock']:
|
||||
index = config['lock'].index(event.code)
|
||||
|
||||
self.horizontal_lock, self.vertical_lock = False, False
|
||||
|
||||
if event.value:
|
||||
if index == 0: self.horizontal_lock = True
|
||||
if index == 1: self.vertical_lock = True
|
||||
|
||||
log.debug(event_to_string(event, state))
|
||||
|
||||
# Update axes
|
||||
old_axes = list(self.axes)
|
||||
|
||||
for axis in range(4):
|
||||
self.axes[axis] = event.stream.state.abs[config['axes'][axis]]
|
||||
self.axes[axis] *= config['dir'][axis]
|
||||
|
||||
if abs(self.axes[axis]) < config['deadband']:
|
||||
self.axes[axis] = 0
|
||||
|
||||
if self.horizontal_lock and axis not in [0, 3]:
|
||||
self.axes[axis] = 0
|
||||
|
||||
if self.vertical_lock and axis not in [1, 2]:
|
||||
self.axes[axis] = 0
|
||||
|
||||
if old_axes != self.axes: changed = True
|
||||
|
||||
if changed: self.changed()
|
||||
445
src/py/inevent/Keys.py
Normal file
445
src/py/inevent/Keys.py
Normal file
@@ -0,0 +1,445 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
# The inevent Python module was adapted from pi3d.event from the pi3d
|
||||
# project.
|
||||
#
|
||||
# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC.
|
||||
# Copyright (c) 2015, Tim Skillman.
|
||||
# Copyright (c) 2015, Paddy Gaunt.
|
||||
# Copyright (c) 2015, Tom Ritchford.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
KEY_ESC = 1
|
||||
KEY_1 = 2
|
||||
KEY_2 = 3
|
||||
KEY_3 = 4
|
||||
KEY_4 = 5
|
||||
KEY_5 = 6
|
||||
KEY_6 = 7
|
||||
KEY_7 = 8
|
||||
KEY_8 = 9
|
||||
KEY_9 = 10
|
||||
KEY_0 = 11
|
||||
KEY_MINUS = 12
|
||||
KEY_EQUAL = 13
|
||||
KEY_BACKSPACE = 14
|
||||
KEY_TAB = 15
|
||||
KEY_Q = 16
|
||||
KEY_W = 17
|
||||
KEY_E = 18
|
||||
KEY_R = 19
|
||||
KEY_T = 20
|
||||
KEY_Y = 21
|
||||
KEY_U = 22
|
||||
KEY_I = 23
|
||||
KEY_O = 24
|
||||
KEY_P = 25
|
||||
KEY_LEFTBRACE = 26
|
||||
KEY_RIGHTBRACE = 27
|
||||
KEY_ENTER = 28
|
||||
KEY_LEFTCTRL = 29
|
||||
KEY_A = 30
|
||||
KEY_S = 31
|
||||
KEY_D = 32
|
||||
KEY_F = 33
|
||||
KEY_G = 34
|
||||
KEY_H = 35
|
||||
KEY_J = 36
|
||||
KEY_K = 37
|
||||
KEY_L = 38
|
||||
KEY_SEMICOLON = 39
|
||||
KEY_APOSTROPHE = 40
|
||||
KEY_GRAVE = 41
|
||||
KEY_LEFTSHIFT = 42
|
||||
KEY_BACKSLASH = 43
|
||||
KEY_Z = 44
|
||||
KEY_X = 45
|
||||
KEY_C = 46
|
||||
KEY_V = 47
|
||||
KEY_B = 48
|
||||
KEY_N = 49
|
||||
KEY_M = 50
|
||||
KEY_COMMA = 51
|
||||
KEY_DOT = 52
|
||||
KEY_SLASH = 53
|
||||
KEY_RIGHTSHIFT = 54
|
||||
KEY_KPASTERISK = 55
|
||||
KEY_LEFTALT = 56
|
||||
KEY_SPACE = 57
|
||||
KEY_CAPSLOCK = 58
|
||||
KEY_F1 = 59
|
||||
KEY_F2 = 60
|
||||
KEY_F3 = 61
|
||||
KEY_F4 = 62
|
||||
KEY_F5 = 63
|
||||
KEY_F6 = 64
|
||||
KEY_F7 = 65
|
||||
KEY_F8 = 66
|
||||
KEY_F9 = 67
|
||||
KEY_F10 = 68
|
||||
KEY_NUMLOCK = 69
|
||||
KEY_SCROLLLOCK = 70
|
||||
KEY_KP7 = 71
|
||||
KEY_KP8 = 72
|
||||
KEY_KP9 = 73
|
||||
KEY_KPMINUS = 74
|
||||
KEY_KP4 = 75
|
||||
KEY_KP5 = 76
|
||||
KEY_KP6 = 77
|
||||
KEY_KPPLUS = 78
|
||||
KEY_KP1 = 79
|
||||
KEY_KP2 = 80
|
||||
KEY_KP3 = 81
|
||||
KEY_KP0 = 82
|
||||
KEY_KPDOT = 83
|
||||
|
||||
KEY_ZENKAKUHANKAKU = 85
|
||||
KEY_102ND = 86
|
||||
KEY_F11 = 87
|
||||
KEY_F12 = 88
|
||||
KEY_RO = 89
|
||||
KEY_KATAKANA = 90
|
||||
KEY_HIRAGANA = 91
|
||||
KEY_HENKAN = 92
|
||||
KEY_KATAKANAHIRAGANA = 93
|
||||
KEY_MUHENKAN = 94
|
||||
KEY_KPJPCOMMA = 95
|
||||
KEY_KPENTER = 96
|
||||
KEY_RIGHTCTRL = 97
|
||||
KEY_KPSLASH = 98
|
||||
KEY_SYSRQ = 99
|
||||
KEY_RIGHTALT = 100
|
||||
KEY_LINEFEED = 101
|
||||
KEY_HOME = 102
|
||||
KEY_UP = 103
|
||||
KEY_PAGEUP = 104
|
||||
KEY_LEFT = 105
|
||||
KEY_RIGHT = 106
|
||||
KEY_END = 107
|
||||
KEY_DOWN = 108
|
||||
KEY_PAGEDOWN = 109
|
||||
KEY_INSERT = 110
|
||||
KEY_DELETE = 111
|
||||
KEY_MACRO = 112
|
||||
KEY_MUTE = 113
|
||||
KEY_VOLUMEDOWN = 114
|
||||
KEY_VOLUMEUP = 115
|
||||
KEY_POWER = 116
|
||||
KEY_KPEQUAL = 117
|
||||
KEY_KPPLUSMINUS = 118
|
||||
KEY_PAUSE = 119
|
||||
|
||||
KEY_KPCOMMA = 121
|
||||
KEY_HANGUEL = 122
|
||||
KEY_HANJA = 123
|
||||
KEY_YEN = 124
|
||||
KEY_LEFTMETA = 125
|
||||
KEY_RIGHTMETA = 126
|
||||
KEY_COMPOSE = 127
|
||||
|
||||
KEY_STOP = 128
|
||||
KEY_AGAIN = 129
|
||||
KEY_PROPS = 130
|
||||
KEY_UNDO = 131
|
||||
KEY_FRONT = 132
|
||||
KEY_COPY = 133
|
||||
KEY_OPEN = 134
|
||||
KEY_PASTE = 135
|
||||
KEY_FIND = 136
|
||||
KEY_CUT = 137
|
||||
KEY_HELP = 138
|
||||
KEY_MENU = 139
|
||||
KEY_CALC = 140
|
||||
KEY_SETUP = 141
|
||||
KEY_SLEEP = 142
|
||||
KEY_WAKEUP = 143
|
||||
KEY_FILE = 144
|
||||
KEY_SENDFILE = 145
|
||||
KEY_DELETEFILE = 146
|
||||
KEY_XFER = 147
|
||||
KEY_PROG1 = 148
|
||||
KEY_PROG2 = 149
|
||||
KEY_WWW = 150
|
||||
KEY_MSDOS = 151
|
||||
KEY_COFFEE = 152
|
||||
KEY_DIRECTION = 153
|
||||
KEY_CYCLEWINDOWS = 154
|
||||
KEY_MAIL = 155
|
||||
KEY_BOOKMARKS = 156
|
||||
KEY_COMPUTER = 157
|
||||
KEY_BACK = 158
|
||||
KEY_FORWARD = 159
|
||||
KEY_CLOSECD = 160
|
||||
KEY_EJECTCD = 161
|
||||
KEY_EJECTCLOSECD = 162
|
||||
KEY_NEXTSONG = 163
|
||||
KEY_PLAYPAUSE = 164
|
||||
KEY_PREVIOUSSONG = 165
|
||||
KEY_STOPCD = 166
|
||||
KEY_RECORD = 167
|
||||
KEY_REWIND = 168
|
||||
KEY_PHONE = 169
|
||||
KEY_ISO = 170
|
||||
KEY_CONFIG = 171
|
||||
KEY_HOMEPAGE = 172
|
||||
KEY_REFRESH = 173
|
||||
KEY_EXIT = 174
|
||||
KEY_MOVE = 175
|
||||
KEY_EDIT = 176
|
||||
KEY_SCROLLUP = 177
|
||||
KEY_SCROLLDOWN = 178
|
||||
KEY_KPLEFTPAREN = 179
|
||||
KEY_KPRIGHTPAREN = 180
|
||||
|
||||
KEY_F13 = 183
|
||||
KEY_F14 = 184
|
||||
KEY_F15 = 185
|
||||
KEY_F16 = 186
|
||||
KEY_F17 = 187
|
||||
KEY_F18 = 188
|
||||
KEY_F19 = 189
|
||||
KEY_F20 = 190
|
||||
KEY_F21 = 191
|
||||
KEY_F22 = 192
|
||||
KEY_F23 = 193
|
||||
KEY_F24 = 194
|
||||
|
||||
KEY_PLAYCD = 200
|
||||
KEY_PAUSECD = 201
|
||||
KEY_PROG3 = 202
|
||||
KEY_PROG4 = 203
|
||||
KEY_SUSPEND = 205
|
||||
KEY_CLOSE = 206
|
||||
KEY_PLAY = 207
|
||||
KEY_FASTFORWARD = 208
|
||||
KEY_BASSBOOST = 209
|
||||
KEY_PRINT = 210
|
||||
KEY_HP = 211
|
||||
KEY_CAMERA = 212
|
||||
KEY_SOUND = 213
|
||||
KEY_QUESTION = 214
|
||||
KEY_EMAIL = 215
|
||||
KEY_CHAT = 216
|
||||
KEY_SEARCH = 217
|
||||
KEY_CONNECT = 218
|
||||
KEY_FINANCE = 219
|
||||
KEY_SPORT = 220
|
||||
KEY_SHOP = 221
|
||||
KEY_ALTERASE = 222
|
||||
KEY_CANCEL = 223
|
||||
KEY_BRIGHTNESSDOWN = 224
|
||||
KEY_BRIGHTNESSUP = 225
|
||||
KEY_MEDIA = 226
|
||||
|
||||
KEY_UNKNOWN = 240
|
||||
|
||||
BTN_MISC = 0x100
|
||||
BTN_0 = 0x100
|
||||
BTN_1 = 0x101
|
||||
BTN_2 = 0x102
|
||||
BTN_3 = 0x103
|
||||
BTN_4 = 0x104
|
||||
BTN_5 = 0x105
|
||||
BTN_6 = 0x106
|
||||
BTN_7 = 0x107
|
||||
BTN_8 = 0x108
|
||||
BTN_9 = 0x109
|
||||
|
||||
BTN_MOUSE = 0x110
|
||||
BTN_LEFT = 0x110
|
||||
BTN_RIGHT = 0x111
|
||||
BTN_MIDDLE = 0x112
|
||||
BTN_SIDE = 0x113
|
||||
BTN_EXTRA = 0x114
|
||||
BTN_FORWARD = 0x115
|
||||
BTN_BACK = 0x116
|
||||
BTN_TASK = 0x117
|
||||
|
||||
BTN_JOYSTICK = 0x120
|
||||
BTN_TRIGGER = 0x120
|
||||
BTN_THUMB = 0x121
|
||||
BTN_THUMB2 = 0x122
|
||||
BTN_TOP = 0x123
|
||||
BTN_TOP2 = 0x124
|
||||
BTN_PINKIE = 0x125
|
||||
BTN_BASE = 0x126
|
||||
BTN_BASE2 = 0x127
|
||||
BTN_BASE3 = 0x128
|
||||
BTN_BASE4 = 0x129
|
||||
BTN_BASE5 = 0x12a
|
||||
BTN_BASE6 = 0x12b
|
||||
BTN_DEAD = 0x12f
|
||||
|
||||
BTN_GAMEPAD = 0x130
|
||||
BTN_A = 0x130
|
||||
BTN_B = 0x131
|
||||
BTN_C = 0x132
|
||||
BTN_X = 0x133
|
||||
BTN_Y = 0x134
|
||||
BTN_Z = 0x135
|
||||
BTN_TL = 0x136
|
||||
BTN_TR = 0x137
|
||||
BTN_TL2 = 0x138
|
||||
BTN_TR2 = 0x139
|
||||
BTN_SELECT = 0x13a
|
||||
BTN_START = 0x13b
|
||||
BTN_MODE = 0x13c
|
||||
BTN_THUMBL = 0x13d
|
||||
BTN_THUMBR = 0x13e
|
||||
|
||||
BTN_DIGI = 0x140
|
||||
BTN_TOOL_PEN = 0x140
|
||||
BTN_TOOL_RUBBER = 0x141
|
||||
BTN_TOOL_BRUSH = 0x142
|
||||
BTN_TOOL_PENCIL = 0x143
|
||||
BTN_TOOL_AIRBRUSH = 0x144
|
||||
BTN_TOOL_FINGER = 0x145
|
||||
BTN_TOOL_MOUSE = 0x146
|
||||
BTN_TOOL_LENS = 0x147
|
||||
BTN_TOUCH = 0x14a
|
||||
BTN_STYLUS = 0x14b
|
||||
BTN_STYLUS2 = 0x14c
|
||||
BTN_TOOL_DOUBLETAP = 0x14d
|
||||
BTN_TOOL_TRIPLETAP = 0x14e
|
||||
|
||||
BTN_WHEEL = 0x150
|
||||
BTN_GEAR_DOWN = 0x150
|
||||
BTN_GEAR_UP = 0x151
|
||||
|
||||
KEY_OK = 0x160
|
||||
KEY_SELECT = 0x161
|
||||
KEY_GOTO = 0x162
|
||||
KEY_CLEAR = 0x163
|
||||
KEY_POWER2 = 0x164
|
||||
KEY_OPTION = 0x165
|
||||
KEY_INFO = 0x166
|
||||
KEY_TIME = 0x167
|
||||
KEY_VENDOR = 0x168
|
||||
KEY_ARCHIVE = 0x169
|
||||
KEY_PROGRAM = 0x16a
|
||||
KEY_CHANNEL = 0x16b
|
||||
KEY_FAVORITES = 0x16c
|
||||
KEY_EPG = 0x16d
|
||||
KEY_PVR = 0x16e
|
||||
KEY_MHP = 0x16f
|
||||
KEY_LANGUAGE = 0x170
|
||||
KEY_TITLE = 0x171
|
||||
KEY_SUBTITLE = 0x172
|
||||
KEY_ANGLE = 0x173
|
||||
KEY_ZOOM = 0x174
|
||||
KEY_MODE = 0x175
|
||||
KEY_KEYBOARD = 0x176
|
||||
KEY_SCREEN = 0x177
|
||||
KEY_PC = 0x178
|
||||
KEY_TV = 0x179
|
||||
KEY_TV2 = 0x17a
|
||||
KEY_VCR = 0x17b
|
||||
KEY_VCR2 = 0x17c
|
||||
KEY_SAT = 0x17d
|
||||
KEY_SAT2 = 0x17e
|
||||
KEY_CD = 0x17f
|
||||
KEY_TAPE = 0x180
|
||||
KEY_RADIO = 0x181
|
||||
KEY_TUNER = 0x182
|
||||
KEY_PLAYER = 0x183
|
||||
KEY_TEXT = 0x184
|
||||
KEY_DVD = 0x185
|
||||
KEY_AUX = 0x186
|
||||
KEY_MP3 = 0x187
|
||||
KEY_AUDIO = 0x188
|
||||
KEY_VIDEO = 0x189
|
||||
KEY_DIRECTORY = 0x18a
|
||||
KEY_LIST = 0x18b
|
||||
KEY_MEMO = 0x18c
|
||||
KEY_CALENDAR = 0x18d
|
||||
KEY_RED = 0x18e
|
||||
KEY_GREEN = 0x18f
|
||||
KEY_YELLOW = 0x190
|
||||
KEY_BLUE = 0x191
|
||||
KEY_CHANNELUP = 0x192
|
||||
KEY_CHANNELDOWN = 0x193
|
||||
KEY_FIRST = 0x194
|
||||
KEY_LAST = 0x195
|
||||
KEY_AB = 0x196
|
||||
KEY_NEXT = 0x197
|
||||
KEY_RESTART = 0x198
|
||||
KEY_SLOW = 0x199
|
||||
KEY_SHUFFLE = 0x19a
|
||||
KEY_BREAK = 0x19b
|
||||
KEY_PREVIOUS = 0x19c
|
||||
KEY_DIGITS = 0x19d
|
||||
KEY_TEEN = 0x19e
|
||||
KEY_TWEN = 0x19f
|
||||
|
||||
KEY_DEL_EOL = 0x1c0
|
||||
KEY_DEL_EOS = 0x1c1
|
||||
KEY_INS_LINE = 0x1c2
|
||||
KEY_DEL_LINE = 0x1c3
|
||||
|
||||
KEY_FN = 0x1d0
|
||||
KEY_FN_ESC = 0x1d1
|
||||
KEY_FN_F1 = 0x1d2
|
||||
KEY_FN_F2 = 0x1d3
|
||||
KEY_FN_F3 = 0x1d4
|
||||
KEY_FN_F4 = 0x1d5
|
||||
KEY_FN_F5 = 0x1d6
|
||||
KEY_FN_F6 = 0x1d7
|
||||
KEY_FN_F7 = 0x1d8
|
||||
KEY_FN_F8 = 0x1d9
|
||||
KEY_FN_F9 = 0x1da
|
||||
KEY_FN_F10 = 0x1db
|
||||
KEY_FN_F11 = 0x1dc
|
||||
KEY_FN_F12 = 0x1dd
|
||||
KEY_FN_1 = 0x1de
|
||||
KEY_FN_2 = 0x1df
|
||||
KEY_FN_D = 0x1e0
|
||||
KEY_FN_E = 0x1e1
|
||||
KEY_FN_F = 0x1e2
|
||||
KEY_FN_S = 0x1e3
|
||||
KEY_FN_B = 0x1e4
|
||||
|
||||
KEY_MAX = 0x1ff
|
||||
57
src/py/inevent/__init__.py
Normal file
57
src/py/inevent/__init__.py
Normal file
@@ -0,0 +1,57 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
# The inevent Python module was adapted from pi3d.event from the pi3d
|
||||
# project.
|
||||
#
|
||||
# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC.
|
||||
# Copyright (c) 2015, Tim Skillman.
|
||||
# Copyright (c) 2015, Paddy Gaunt.
|
||||
# Copyright (c) 2015, Tom Ritchford.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from .InEvent import InEvent
|
||||
from .JogHandler import JogHandler
|
||||
128
src/py/inevent/ioctl.py
Normal file
128
src/py/inevent/ioctl.py
Normal file
@@ -0,0 +1,128 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
# The inevent Python module was adapted from pi3d.event from the pi3d
|
||||
# project.
|
||||
#
|
||||
# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC.
|
||||
# Copyright (c) 2015, Tim Skillman.
|
||||
# Copyright (c) 2015, Paddy Gaunt.
|
||||
# Copyright (c) 2015, Tom Ritchford.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# IOCTL macros
|
||||
#
|
||||
# ioctl command encoding: 32 bits total, command in lower 16 bits,
|
||||
# size of the parameter structure in the lower 14 bits of the
|
||||
# upper 16 bits.
|
||||
#
|
||||
# Encoding the size of the parameter structure in the ioctl request
|
||||
# is useful for catching programs compiled with old versions
|
||||
# and to avoid overwriting user space outside the user buffer area.
|
||||
# The highest 2 bits are reserved for indicating the ``access mode''.
|
||||
# NOTE: This limits the max parameter size to 16kB - 1
|
||||
#
|
||||
# The following is for compatibility across the various Linux
|
||||
# platforms. The generic ioctl numbering scheme doesn't really enforce
|
||||
# a type field. De facto, however, the top 8 bits of the lower 16
|
||||
# bits are indeed used as a type field, so we might just as well make
|
||||
# this explicit here.
|
||||
|
||||
import struct
|
||||
|
||||
|
||||
sizeof = struct.calcsize
|
||||
|
||||
_IOC_NRBITS = 8
|
||||
_IOC_TYPEBITS = 8
|
||||
_IOC_SIZEBITS = 14
|
||||
_IOC_DIRBITS = 2
|
||||
|
||||
_IOC_NRMASK = (1 << _IOC_NRBITS) - 1
|
||||
_IOC_TYPEMASK = (1 << _IOC_TYPEBITS) - 1
|
||||
_IOC_SIZEMASK = (1 << _IOC_SIZEBITS) - 1
|
||||
_IOC_DIRMASK = (1 << _IOC_DIRBITS) - 1
|
||||
|
||||
_IOC_NRSHIFT = 0
|
||||
_IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS
|
||||
_IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS
|
||||
_IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS
|
||||
|
||||
_IOC_NONE = 0
|
||||
_IOC_WRITE = 1
|
||||
_IOC_READ = 2
|
||||
_IOC_RW = _IOC_READ | _IOC_WRITE
|
||||
|
||||
|
||||
def _IOC(dir, type, nr, size):
|
||||
return int(
|
||||
(dir << _IOC_DIRSHIFT) |
|
||||
(type << _IOC_TYPESHIFT) |
|
||||
(nr << _IOC_NRSHIFT) |
|
||||
(size << _IOC_SIZESHIFT))
|
||||
|
||||
# encode ioctl numbers
|
||||
def _IO(type, nr): return _IOC(_IOC_NONE, type, nr, 0)
|
||||
def _IOR(type, nr, fmt): return _IOC(_IOC_READ, type, nr, sizeof(fmt))
|
||||
def _IOW(type, nr, fmt): return _IOC(_IOC_WRITE, type, nr, sizeof(fmt))
|
||||
def _IOWR(type, nr, fmt): return _IOC(_IOC_RW, type, nr, sizeof(fmt))
|
||||
def _IOR_BAD(type, nr, fmt): return _IOC(_IOC_READ, type, nr, sizeof(fmt))
|
||||
def _IOW_BAD(type, nr, fmt): return _IOC(_IOC_WRITE, type, nr, sizeof(fmt))
|
||||
def _IOWR_BAD(type, nr, fmt): return _IOC(_IOC_RW, type, nr, sizeof(fmt))
|
||||
|
||||
# decode ioctl numbers
|
||||
def _IOC_DIR(nr): return (nr >> _IOC_DIRSHIFT) & _IOC_DIRMASK
|
||||
def _IOC_TYPE(nr): return (nr >> _IOC_TYPESHIFT) & _IOC_TYPEMASK
|
||||
def _IOC_NR(nr): return (nr >> _IOC_NRSHIFT) & _IOC_NRMASK
|
||||
def _IOC_SIZE(nr): return (nr >> _IOC_SIZESHIFT) & _IOC_SIZEMASK
|
||||
|
||||
# for drivers/sound files
|
||||
IOC_IN = _IOC_WRITE << _IOC_DIRSHIFT
|
||||
IOC_OUT = _IOC_READ << _IOC_DIRSHIFT
|
||||
IOC_INOUT = _IOC_RW << _IOC_DIRSHIFT
|
||||
IOCSIZE_MASK = _IOC_SIZEMASK << _IOC_SIZESHIFT
|
||||
IOCSIZE_SHIFT = _IOC_SIZESHIFT
|
||||
|
||||
Reference in New Issue
Block a user