2 Linux Input Device support.
3 Copyright (c) 2004 stefan kersten.
4 modifications by Marije Baalman 2006-9
6 ====================================================================
8 SuperCollider real time audio synthesis system
9 Copyright (c) 2002 James McCartney. All rights reserved.
10 http://www.audiosynth.com
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 Linux Input Device interface, 2004 <sk>
30 #include "VMGlobals.h"
31 #include "PyrSymbolTable.h"
32 #include "PyrInterpreter.h"
33 #include "PyrKernel.h"
35 #include "PyrPrimitive.h"
36 #include "PyrObjectProto.h"
37 #include "PyrPrimitiveProto.h"
38 #include "PyrKernelProto.h"
39 #include "SC_InlineUnaryOp.h"
40 #include "SC_InlineBinaryOp.h"
47 #include <linux/input.h>
50 #include <sys/select.h>
51 #include <sys/types.h>
54 #define BITS_PER_LONG (sizeof(long) * 8)
55 #define NBITS(x) ((((x) - 1) / BITS_PER_LONG) + 1)
56 #define OFF(x) ((x) % BITS_PER_LONG)
57 #define BIT(x) (1UL << OFF(x))
58 #define LONG(x) ((x) / BITS_PER_LONG)
59 #define TEST_BIT(array, bit) (((array)[LONG(bit)] >> OFF(bit)) & 1)
61 extern bool compiledOK
;
63 static PyrSymbol
* s_inputDeviceClass
= 0;
64 static PyrSymbol
* s_inputDeviceInfoClass
= 0;
65 static PyrSymbol
* s_absInfoClass
= 0;
66 static PyrSymbol
* s_handleEvent
= 0;
67 static PyrSymbol
* s_readError
= 0;
69 // =====================================================================
74 SC_LID(PyrObject
*obj
);
77 int open(const char *path
);
80 bool isEventTypeSupported(int evtType
);
81 bool isEventCodeSupported(int evtType
, int evtCode
);
83 int getName(char* buf
, size_t size
);
84 int getInfo(struct input_id
*info
, char *bufPhys
, size_t sizePhys
, char *bufUniq
, size_t sizeUniq
);
85 int getKeyState(int evtCode
);
86 int getAbsInfo(int evtCode
, struct input_absinfo
*info
);
88 int setLedState( int evtCode
, int evtValue
, int evtType
);
91 void handleEvent(struct input_event
& evt
);
94 static PyrObject
* getObject(PyrSlot
* slot
)
96 return isKindOfSlot(slot
, s_inputDeviceClass
->u
.classobj
) ? slotRawObject(slot
) : 0;
99 static SC_LID
* getDevice(PyrObject
* obj
)
101 return (SC_LID
*)slotRawPtr(&obj
->slots
[0]);
108 unsigned long m_eventTypeCaps
[NBITS(EV_MAX
)];
109 unsigned long m_eventCodeCaps
[NBITS(KEY_MAX
)];
110 unsigned long m_keyState
[NBITS(KEY_MAX
)];
113 // =====================================================================
119 static SC_LIDManager
& instance();
124 int add(SC_LID
*dev
);
125 int remove(SC_LID
*dev
);
147 int sendCommand(const Command
& cmd
);
148 void devicesChanged();
149 bool asyncAddDevice(SC_LID
*dev
);
150 bool asyncRemoveDevice(SC_LID
*dev
);
153 static void* threadFunc(void*);
156 pthread_mutex_t m_mutex
;
164 // =====================================================================
167 SC_LID::SC_LID(PyrObject
* obj
)
173 SetPtr(obj
->slots
+0, this);
178 if (m_fd
!= -1) ::close(m_fd
);
181 int SC_LID::open(const char* path
)
183 m_fd
= ::open(path
, O_RDWR
);
186 error("LID (1): %s\n", strerror(errno
));
190 memset(m_eventTypeCaps
, 0, sizeof(m_eventTypeCaps
));
191 if (ioctl(m_fd
, EVIOCGBIT(0, EV_MAX
), m_eventTypeCaps
) == -1) {
192 error("LID (2): %s\n", strerror(errno
));
196 memset(m_keyState
, 0, sizeof(m_keyState
));
197 if (ioctl(m_fd
, EVIOCGKEY(sizeof(m_keyState
)), m_keyState
) == -1) {
198 error("LID (3): %s\n", strerror(errno
));
202 return SC_LIDManager::instance().add(this);
207 SetNil(m_obj
->slots
+0);
208 return SC_LIDManager::instance().remove(this);
211 bool SC_LID::isEventTypeSupported(int evtType
)
213 return TEST_BIT(m_eventTypeCaps
, evtType
);
216 bool SC_LID::isEventCodeSupported(int evtType
, int evtCode
)
218 if (evtType
!= m_lastEventType
) {
219 m_lastEventType
= evtType
;
220 memset(m_eventCodeCaps
, 0, sizeof(m_eventCodeCaps
));
221 if (ioctl(m_fd
, EVIOCGBIT(evtType
, KEY_MAX
), m_eventCodeCaps
) == -1) {
222 post("LID failed to check event code (error %s)\n", strerror(errno
));
226 return TEST_BIT(m_eventCodeCaps
, evtCode
);
229 int SC_LID::getName(char* buf
, size_t size
)
231 if (ioctl(m_fd
, EVIOCGNAME(size
), buf
) == -1) {
232 error("LID (5): %s\n", strerror(errno
));
238 int SC_LID::getInfo(struct input_id
*info
, char *bufPhys
, size_t sizePhys
, char *bufUniq
, size_t sizeUniq
)
240 if (ioctl(m_fd
, EVIOCGID
, info
) == -1) {
241 error("LID (6): %s\n", strerror(errno
));
244 if (ioctl(m_fd
, EVIOCGPHYS(sizePhys
), bufPhys
) == -1) {
245 // strcpy( sizePhys, strerror(errno));
246 post("LID could not retrieve physical location (error: %s)\n", strerror(errno
));
249 if (ioctl(m_fd
, EVIOCGUNIQ(sizeUniq
), bufUniq
) == -1) {
250 // strcpy( strerror(errno), sizeof( strerror(errno)), sizeUniq );
251 post("LID could not get unique identifier (error: %s)\n", strerror(errno
));
258 int SC_LID::getKeyState(int evtCode
)
260 return TEST_BIT(m_keyState
, evtCode
);
263 int SC_LID::getAbsInfo(int evtCode
, struct input_absinfo
* info
)
265 if (ioctl(m_fd
, EVIOCGABS(evtCode
), info
) == -1) {
266 error("LID (9): %s\n", strerror(errno
));
272 int SC_LID::setLedState( int evtCode
, int evtValue
, int evtType
)
273 { // added by marije baalman
274 struct input_event ev
;
275 // post( "set led state called, putting event" );
279 // post( "m_fd %i", m_fd );
280 // post( "code %i, value %i ", evtCode, evtValue );
281 if ( write(m_fd
, &ev
, sizeof(struct input_event
)) == -1 )
283 // post( "error writing event" );
289 int SC_LID::grab(int flag
)
291 if (ioctl(m_fd
, EVIOCGRAB
, flag
) == -1) {
292 error("LID (10): %s\n", strerror(errno
));
298 void SC_LID::handleEvent(struct input_event
& evt
)
300 if (evt
.type
!= EV_SYN
) {
301 pthread_mutex_lock(&gLangMutex
);
303 VMGlobals
* g
= gMainVMGlobals
;
304 g
->canCallOS
= false;
305 ++g
->sp
; SetObject(g
->sp
, m_obj
);
306 ++g
->sp
; SetInt(g
->sp
, evt
.type
);
307 ++g
->sp
; SetInt(g
->sp
, evt
.code
);
308 ++g
->sp
; SetInt(g
->sp
, evt
.value
);
309 runInterpreter(g
, s_handleEvent
, 4);
310 g
->canCallOS
= false;
312 pthread_mutex_unlock(&gLangMutex
);
316 void SC_LID::readError()
318 pthread_mutex_lock(&gLangMutex
);
320 VMGlobals
* g
= gMainVMGlobals
;
321 g
->canCallOS
= false;
322 ++g
->sp
; SetObject(g
->sp
, m_obj
);
323 runInterpreter(g
, s_readError
, 1);
324 g
->canCallOS
= false;
326 pthread_mutex_unlock(&gLangMutex
);
329 // =====================================================================
332 SC_LIDManager
& SC_LIDManager::instance()
334 static SC_LIDManager instance
;
338 SC_LIDManager::SC_LIDManager()
342 if (pipe(m_cmdFifo
) == -1) {
343 m_cmdFifo
[0] = m_cmdFifo
[1] = -1;
348 SC_LIDManager::~SC_LIDManager()
354 int SC_LIDManager::start()
357 err
= pthread_create(&m_thread
, 0, &threadFunc
, this);
358 if (err
!= 0) return errFailed
;
362 int SC_LIDManager::stop()
364 if (m_running
== false)
370 int err
= sendCommand(cmd
);
373 err
= pthread_join(m_thread
, 0);
374 if (err
!= 0) return errFailed
;
379 int SC_LIDManager::add(SC_LID
* dev
)
384 return sendCommand(cmd
);
387 int SC_LIDManager::remove(SC_LID
* dev
)
392 return sendCommand(cmd
);
395 int SC_LIDManager::sendCommand(const Command
& cmd
)
397 return write(m_cmdFifo
[1], &cmd
, sizeof(cmd
)) == sizeof(cmd
) ? errNone
: errFailed
;
400 void SC_LIDManager::devicesChanged()
402 int fdMax
= m_cmdFifo
[0];
405 FD_SET(fdMax
, &m_fds
);
407 SC_LID
*dev
= m_devices
;
412 if (fd
> fdMax
) fdMax
= fd
;
420 bool SC_LIDManager::asyncAddDevice(SC_LID
* dev
)
422 if (dev
->m_next
) return false;
423 dev
->m_next
= m_devices
;
429 bool SC_LIDManager::asyncRemoveDevice(SC_LID
* dev
)
431 SC_LID
*prev
= 0, *cur
= m_devices
;
435 if (prev
) prev
->m_next
= dev
->m_next
;
436 else m_devices
= dev
->m_next
;
449 void* SC_LIDManager::threadFunc(void* arg
)
451 ((SC_LIDManager
*)arg
)->loop();
455 void SC_LIDManager::loop()
458 post("LID: event loop started\n");
462 memcpy(&fds
, &m_fds
, sizeof(fd_set
));
463 int n
= select(m_nfds
, &fds
, 0, 0, 0);
465 if( errno
== EINTR
) continue;
466 post("LID: error in input handler: %s\n", strerror(errno
));
469 if (FD_ISSET(m_cmdFifo
[0], &fds
)) {
472 int err
= read(m_cmdFifo
[0], &cmd
, sizeof(cmd
));
474 if( errno
!= EINTR
) {
475 post("LID: error in input handler: %s\n", strerror(errno
));
484 if (asyncAddDevice(cmd
.arg
.dev
)) {
485 post("LID: added device %p\n", cmd
.arg
);
487 post("LID: cannot add device\n");
491 if (asyncRemoveDevice(cmd
.arg
.dev
)) {
492 post("LID: removed device %p\n", cmd
.arg
);
494 post("LID: couldn't remove device\n");
498 post("LID: unknown command in input handler\n");
503 SC_LID
*dev
= m_devices
;
506 if (FD_ISSET(fd
, &fds
)) {
507 struct input_event evt
;
508 if (read(fd
, &evt
, sizeof(evt
)) == sizeof(evt
)) {
509 dev
->handleEvent(evt
);
523 post("LID: event loop stopped\n");
526 // =====================================================================
527 // Primitive Interface
529 int prLID_Open(VMGlobals
*g
, int numArgsPushed
)
531 PyrSlot
* args
= g
->sp
- 1;
534 PyrObject
* obj
= SC_LID::getObject(args
+0);
535 if (!obj
) return errWrongType
;
538 err
= slotStrVal(args
+1, path
, sizeof(path
));
541 SC_LID
* dev
= new SC_LID(obj
);
542 err
= dev
->open(path
);
551 int prLID_Close(VMGlobals
*g
, int numArgsPushed
)
553 PyrSlot
* args
= g
->sp
;
555 PyrObject
* obj
= SC_LID::getObject(args
+0);
556 if (!obj
) return errWrongType
;
558 SC_LID
* dev
= SC_LID::getDevice(obj
);
559 if (!dev
) return errFailed
;
564 int prLID_EventTypeSupported(VMGlobals
*g
, int numArgsPushed
)
566 PyrSlot
* args
= g
->sp
- 1;
570 if (!g
->canCallOS
) return errCantCallOS
;
572 PyrObject
* obj
= SC_LID::getObject(args
+0);
573 if (!obj
) return errWrongType
;
575 err
= slotIntVal(args
+1, &evtType
);
578 SC_LID
* dev
= SC_LID::getDevice(obj
);
579 if (!dev
) return errFailed
;
581 SetBool(args
, dev
->isEventTypeSupported(evtType
));
586 int prLID_EventCodeSupported(VMGlobals
*g
, int numArgsPushed
)
588 PyrSlot
* args
= g
->sp
- 2;
589 int evtType
, evtCode
;
592 if (!g
->canCallOS
) return errCantCallOS
;
594 PyrObject
* obj
= SC_LID::getObject(args
+0);
595 if (!obj
) return errWrongType
;
597 err
= slotIntVal(args
+1, &evtType
);
600 err
= slotIntVal(args
+2, &evtCode
);
603 SC_LID
* dev
= SC_LID::getDevice(obj
);
604 if (!dev
) return errFailed
;
606 SetBool(args
, dev
->isEventCodeSupported(evtType
, evtCode
));
611 int prLID_GetInfo(VMGlobals
* g
, int numArgsPushed
)
613 PyrSlot
* args
= g
->sp
- 1;
616 PyrObject
* obj
= SC_LID::getObject(args
+0);
617 if (!obj
) return errWrongType
;
619 if (!isKindOfSlot(args
+1, s_inputDeviceInfoClass
->u
.classobj
))
621 PyrObject
* infoObj
= slotRawObject(&args
[1]);
623 SC_LID
* dev
= SC_LID::getDevice(obj
);
624 if (!dev
) return errFailed
;
627 err
= dev
->getName(name
, sizeof(name
));
630 struct input_id info
;
633 err
= dev
->getInfo(&info
, namePhys
, sizeof( namePhys
), nameUniq
, sizeof( nameUniq
) );
636 SetSymbol(infoObj
->slots
+0, getsym(name
));
637 SetInt(infoObj
->slots
+1, info
.bustype
);
638 SetInt(infoObj
->slots
+2, info
.vendor
);
639 SetInt(infoObj
->slots
+3, info
.product
);
640 SetInt(infoObj
->slots
+4, info
.version
);
641 SetSymbol(infoObj
->slots
+5, getsym(namePhys
));
642 SetSymbol(infoObj
->slots
+6, getsym(nameUniq
));
644 slotCopy(&args
[0], &args
[1]);
649 int prLID_GetKeyState(VMGlobals
*g
, int numArgsPushed
)
651 PyrSlot
* args
= g
->sp
- 1;
655 PyrObject
* obj
= SC_LID::getObject(args
+0);
656 if (!obj
) return errWrongType
;
658 err
= slotIntVal(args
+1, &evtCode
);
661 SC_LID
* dev
= SC_LID::getDevice(obj
);
662 if (!dev
) return errFailed
;
664 SetInt(args
, dev
->getKeyState(evtCode
));
669 int prLID_GetAbsInfo(VMGlobals
*g
, int numArgsPushed
)
671 PyrSlot
* args
= g
->sp
- 2;
675 PyrObject
* obj
= SC_LID::getObject(args
+0);
676 if (!obj
) return errWrongType
;
678 err
= slotIntVal(args
+1, &evtCode
);
681 if (!isKindOfSlot(args
+2, s_absInfoClass
->u
.classobj
))
683 PyrObject
* infoObj
= slotRawObject(&args
[2]);
685 SC_LID
* dev
= SC_LID::getDevice(obj
);
686 if (!dev
) return errFailed
;
688 struct input_absinfo info
;
689 err
= dev
->getAbsInfo(evtCode
, &info
);
692 SetInt(infoObj
->slots
+0, info
.value
);
693 SetInt(infoObj
->slots
+1, info
.minimum
);
694 SetInt(infoObj
->slots
+2, info
.maximum
);
695 SetInt(infoObj
->slots
+3, info
.fuzz
);
696 SetInt(infoObj
->slots
+4, info
.flat
);
698 slotCopy(&args
[0], &args
[2]);
703 int prLID_Grab(VMGlobals
*g
, int numArgsPushed
)
705 PyrSlot
* args
= g
->sp
- 1;
707 PyrObject
* obj
= SC_LID::getObject(args
+0);
708 if (!obj
) return errWrongType
;
710 SC_LID
* dev
= SC_LID::getDevice(obj
);
711 if (!dev
) return errFailed
;
713 return dev
->grab(IsTrue(args
+1));
716 int prLID_Start(VMGlobals
* g
, int numArgsPushed
)
718 // if (!g->canCallOS) return errCantCallOS;
719 return SC_LIDManager::instance().start();
722 int prLID_Stop(VMGlobals
* g
, int numArgsPushed
)
724 // if (!g->canCallOS) return errCantCallOS;
725 return SC_LIDManager::instance().stop();
728 int prLID_SetLedState(VMGlobals
*g
, int numArgsPushed
)
730 // post( "set led state primitive called" );
731 PyrSlot
* args
= g
->sp
- 2;
732 int evtCode
, evtValue
;
735 PyrObject
* obj
= SC_LID::getObject(args
+0);
736 if (!obj
) return errWrongType
;
738 err
= slotIntVal(args
+1, &evtCode
);
741 err
= slotIntVal(args
+2, &evtValue
);
744 SC_LID
* dev
= SC_LID::getDevice(obj
);
745 if (!dev
) return errFailed
;
747 SetInt(args
, dev
->setLedState(evtCode
,evtValue
, EV_LED
));
751 int prLID_SetMscState(VMGlobals
*g
, int numArgsPushed
)
753 // post( "set msc state primitive called\n" );
754 PyrSlot
* args
= g
->sp
- 2;
755 int evtCode
, evtValue
;
758 PyrObject
* obj
= SC_LID::getObject(args
+0);
759 if (!obj
) return errWrongType
;
761 err
= slotIntVal(args
+1, &evtCode
);
764 err
= slotIntVal(args
+2, &evtValue
);
767 SC_LID
* dev
= SC_LID::getDevice(obj
);
768 if (!dev
) return errFailed
;
770 SetInt(args
, dev
->setLedState(evtCode
,evtValue
, EV_MSC
));
778 s_inputDeviceClass
= getsym("LID");
779 s_inputDeviceInfoClass
= getsym("LIDInfo");
780 s_absInfoClass
= getsym("LIDAbsInfo");
781 s_handleEvent
= getsym("prHandleEvent");
782 s_readError
= getsym("prReadError");
784 base
= nextPrimitiveIndex();
787 definePrimitive(base
, index
++, "_LID_Open", prLID_Open
, 2, 0);
788 definePrimitive(base
, index
++, "_LID_Close", prLID_Close
, 1, 0);
789 definePrimitive(base
, index
++, "_LID_EventTypeSupported", prLID_EventTypeSupported
, 2, 0);
790 definePrimitive(base
, index
++, "_LID_EventCodeSupported", prLID_EventCodeSupported
, 3, 0);
791 definePrimitive(base
, index
++, "_LID_GetInfo", prLID_GetInfo
, 2, 0);
792 definePrimitive(base
, index
++, "_LID_GetKeyState", prLID_GetKeyState
, 2, 0);
793 definePrimitive(base
, index
++, "_LID_GetAbsInfo", prLID_GetAbsInfo
, 3, 0);
794 definePrimitive(base
, index
++, "_LID_Grab", prLID_Grab
, 2, 0);
795 definePrimitive(base
, index
++, "_LID_Start", prLID_Start
, 1, 0);
796 definePrimitive(base
, index
++, "_LID_Stop", prLID_Stop
, 1, 0);
797 definePrimitive(base
, index
++, "_LID_SetLedState", prLID_SetLedState
, 3, 0); // added by Marije Baalman
798 definePrimitive(base
, index
++, "_LID_SetMscState", prLID_SetMscState
, 3, 0);
801 int prLID_Start(VMGlobals
* g
, int numArgsPushed
)
806 int prLID_Stop(VMGlobals
* g
, int numArgsPushed
)
815 base
= nextPrimitiveIndex();
818 definePrimitive(base
, index
++, "_LID_Start", prLID_Start
, 1, 0);
819 definePrimitive(base
, index
++, "_LID_Stop", prLID_Stop
, 1, 0);
823 void initHIDPrimitives()