From 2ba8a63b903fae7bdf1b90bb8ca1bcacf8563ebf Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 22 Apr 2012 07:54:35 +1000 Subject: [PATCH] Add lib/vibra.py The vibrator in the GTA04 is presented as an input device with the 'rumble' force-feedback effect. This python module provides easy access. Signed-off-by: NeilBrown --- lib/vibra.py | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 lib/vibra.py diff --git a/lib/vibra.py b/lib/vibra.py new file mode 100644 index 0000000..7d154c4 --- /dev/null +++ b/lib/vibra.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python + +# Copyright (C) 2011 Neil Brown +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import fcntl, struct, array + +# +# There are two steps to creating a rumble effect +# 1/ describe the effect and give it to the driver using an +# ioctl. +# There a 3 paramaters: +# strength: from 0 to 0xffff - this code takes a value from 0 to +# 1 and scales it +# duration: milliseconds +# delay until start: milliseconds. +# +# 2/ write a request to play a specific effect. +# +# It is possible to have multiple effects active. If they have +# different delays they will start at different times. +# This demo shows combining 3 non-overlapping effects to make +# a simple vibration pattern +# +# An effect is created with f.new_vibe(strength, duration, delay) +# That effect can then be started with 'play' and stopped with 'stop'. + +# EVIOCRMFF = _IOW('E', 0x81, int) +# dir: 2 WRITE = 1 == 0x40000 +# size 14 4 +# type 8 'E' == 0x45 +# nr: 8 0x81 +# +EVIOCRMFF = 0x40044581 +# EVIOCSFF _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect)) +EVIOCSFF = 0x402c4580 +class Vibra: + def __init__(self, file = "/dev/input/rumble"): + self.f = open(file, "r+") + + def close(self): + self.f.close() + + def new_vibe(self, strength, length, delay): + # strength is from 0 to 1 + # length and delay are in millisecs + # this is 'struct ff_effect' from "linux/input.h" + effect = struct.pack('HhHHHHHxxHH', + 0x50, -1, 0, # FF_RUMBLE, id, direction + 0, 0, # trigger (button interval) + length, delay, + int(strength * 0xFFFF), 0) + a = array.array('h', effect) + fcntl.ioctl(self.f, EVIOCSFF, a, True) + return a[1] + id = a[1] + return (ev_play, ev_stop) + + def multi_vibe(self, length, repeats = 1, delay = None, strength = 1): + start = 0 + if delay == None: + delay = length + v = [] + for i in range(0, repeats): + v.append(self.new_vibe(strength, length, start)) + start += length + delay + return v + + def play(self, id): + # this is 'struct input_event': sec, nsec, type, code, value + if type(id) == tuple or type(id) == list: + ev_play = '' + for i in id: + ev_play = ev_play + struct.pack('LLHHi', 0, 0, 0x15, i, 1) + else: + ev_play = struct.pack('LLHHi', 0, 0, 0x15, id, 1) + self.f.write(ev_play) + self.f.flush() + + def stop(self, id): + # this is 'struct input_event': sec, nsec, type, code, value + if type(id) == tuple or type(id) == list: + ev_stop = '' + for i in id: + ev_stop = ev_stop + struct.pack('LLHHi', 0, 0, 0x15, i, 0) + else: + ev_stop = struct.pack('LLHHi', 0, 0, 0x15, id, 0) + self.f.write(ev_stop) + self.f.flush() + + def forget(self, id): + if type(id) == tuple or type(id) == list: + for i in id: + fcntl.ioctl(self.f, EVIOCRMFF, i) + else: + fcntl.ioctl(self.f, EVIOCRMFF, id) + +if __name__ == '__main__': + import time + f = Vibra("/dev/input/rumble") + + # rumble for 300ms, pause for 100ms, rumble for 300ms, pause for 200ms + # then half-speed rumble for 600ms + p1 = f.new_vibe(1, 300, 0) + p2 = f.new_vibe(1, 300,400) + p3 = f.new_vibe(0.5, 600, 900) + + f.play((p1, p2, p3)) + + time.sleep(2) + f.forget((p1, p2, p3)) + + # 14 consecutives 200ms rumbles with 100ms gaps + f.play(f.multi_vibe(200, 14, delay=100)) + + time.sleep(5) -- 2.39.5