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"
43 #include <boost/atomic.hpp>
44 #include "SC_LanguageClient.h"
49 #include <linux/input.h>
52 #include <sys/select.h>
53 #include <sys/types.h>
56 #define BITS_PER_LONG (sizeof(long) * 8)
57 #define NBITS(x) ((((x) - 1) / BITS_PER_LONG) + 1)
58 #define OFF(x) ((x) % BITS_PER_LONG)
59 #define BIT(x) (1UL << OFF(x))
60 #define LONG(x) ((x) / BITS_PER_LONG)
61 #define TEST_BIT(array, bit) (((array)[LONG(bit)] >> OFF(bit)) & 1)
63 extern bool compiledOK
;
65 static PyrSymbol
* s_inputDeviceClass
= 0;
66 static PyrSymbol
* s_inputDeviceInfoClass
= 0;
67 static PyrSymbol
* s_absInfoClass
= 0;
68 static PyrSymbol
* s_handleEvent
= 0;
69 static PyrSymbol
* s_readError
= 0;
71 // =====================================================================
76 SC_LID(PyrObject
*obj
);
79 int open(const char *path
);
82 bool isEventTypeSupported(int evtType
);
83 bool isEventCodeSupported(int evtType
, int evtCode
);
85 int getName(char* buf
, size_t size
);
86 int getInfo(struct input_id
*info
, char *bufPhys
, size_t sizePhys
, char *bufUniq
, size_t sizeUniq
);
87 int getKeyState(int evtCode
);
88 int getAbsInfo(int evtCode
, struct input_absinfo
*info
);
90 int setLedState( int evtCode
, int evtValue
, int evtType
);
93 void handleEvent(struct input_event
& evt
, boost::atomic
<bool> const & shouldBeRunning
);
94 void readError(boost::atomic
<bool> const & shouldBeRunning
);
96 static PyrObject
* getObject(PyrSlot
* slot
)
98 return isKindOfSlot(slot
, s_inputDeviceClass
->u
.classobj
) ? slotRawObject(slot
) : 0;
101 static SC_LID
* getDevice(PyrObject
* obj
)
103 return (SC_LID
*)slotRawPtr(&obj
->slots
[0]);
110 unsigned long m_eventTypeCaps
[NBITS(EV_MAX
)];
111 unsigned long m_eventCodeCaps
[NBITS(KEY_MAX
)];
112 unsigned long m_keyState
[NBITS(KEY_MAX
)];
115 // =====================================================================
121 static SC_LIDManager
& instance();
126 int add(SC_LID
*dev
);
127 int remove(SC_LID
*dev
);
149 int sendCommand(const Command
& cmd
);
150 void devicesChanged();
151 bool asyncAddDevice(SC_LID
*dev
);
152 bool asyncRemoveDevice(SC_LID
*dev
);
155 static void* threadFunc(void*);
158 pthread_mutex_t m_mutex
;
159 boost::atomic
<bool> m_running
;
160 boost::atomic
<bool> mShouldBeRunning
;
167 // =====================================================================
170 SC_LID::SC_LID(PyrObject
* obj
)
176 SetPtr(obj
->slots
+0, this);
181 if (m_fd
!= -1) ::close(m_fd
);
184 int SC_LID::open(const char* path
)
186 m_fd
= ::open(path
, O_RDWR
);
189 error("LID (1): %s\n", strerror(errno
));
193 memset(m_eventTypeCaps
, 0, sizeof(m_eventTypeCaps
));
194 if (ioctl(m_fd
, EVIOCGBIT(0, EV_MAX
), m_eventTypeCaps
) == -1) {
195 error("LID (2): %s\n", strerror(errno
));
199 memset(m_keyState
, 0, sizeof(m_keyState
));
200 if (ioctl(m_fd
, EVIOCGKEY(sizeof(m_keyState
)), m_keyState
) == -1) {
201 error("LID (3): %s\n", strerror(errno
));
205 return SC_LIDManager::instance().add(this);
210 SetNil(m_obj
->slots
+0);
211 return SC_LIDManager::instance().remove(this);
214 bool SC_LID::isEventTypeSupported(int evtType
)
216 return TEST_BIT(m_eventTypeCaps
, evtType
);
219 bool SC_LID::isEventCodeSupported(int evtType
, int evtCode
)
221 if (evtType
!= m_lastEventType
) {
222 m_lastEventType
= evtType
;
223 memset(m_eventCodeCaps
, 0, sizeof(m_eventCodeCaps
));
224 if (ioctl(m_fd
, EVIOCGBIT(evtType
, KEY_MAX
), m_eventCodeCaps
) == -1) {
225 post("LID failed to check event code (error %s)\n", strerror(errno
));
229 return TEST_BIT(m_eventCodeCaps
, evtCode
);
232 int SC_LID::getName(char* buf
, size_t size
)
234 if (ioctl(m_fd
, EVIOCGNAME(size
), buf
) == -1) {
235 error("LID (5): %s\n", strerror(errno
));
241 int SC_LID::getInfo(struct input_id
*info
, char *bufPhys
, size_t sizePhys
, char *bufUniq
, size_t sizeUniq
)
243 if (ioctl(m_fd
, EVIOCGID
, info
) == -1) {
244 error("LID (6): %s\n", strerror(errno
));
247 if (ioctl(m_fd
, EVIOCGPHYS(sizePhys
), bufPhys
) == -1) {
248 // strcpy( sizePhys, strerror(errno));
249 post("LID could not retrieve physical location (error: %s)\n", strerror(errno
));
252 if (ioctl(m_fd
, EVIOCGUNIQ(sizeUniq
), bufUniq
) == -1) {
253 // strcpy( strerror(errno), sizeof( strerror(errno)), sizeUniq );
254 post("LID could not get unique identifier (error: %s)\n", strerror(errno
));
261 int SC_LID::getKeyState(int evtCode
)
263 return TEST_BIT(m_keyState
, evtCode
);
266 int SC_LID::getAbsInfo(int evtCode
, struct input_absinfo
* info
)
268 if (ioctl(m_fd
, EVIOCGABS(evtCode
), info
) == -1) {
269 error("LID (9): %s\n", strerror(errno
));
275 int SC_LID::setLedState( int evtCode
, int evtValue
, int evtType
)
276 { // added by marije baalman
277 struct input_event ev
;
278 // post( "set led state called, putting event" );
282 // post( "m_fd %i", m_fd );
283 // post( "code %i, value %i ", evtCode, evtValue );
284 if ( write(m_fd
, &ev
, sizeof(struct input_event
)) == -1 )
286 // post( "error writing event" );
292 int SC_LID::grab(int flag
)
294 if (ioctl(m_fd
, EVIOCGRAB
, flag
) == -1) {
295 error("LID (10): %s\n", strerror(errno
));
301 void SC_LID::handleEvent(struct input_event
& evt
, boost::atomic
<bool> const & shouldBeRunning
)
303 if (evt
.type
!= EV_SYN
) {
304 int status
= lockLanguageOrQuit(shouldBeRunning
);
308 postfl("error when locking language (%d)\n", status
);
313 VMGlobals
* g
= gMainVMGlobals
;
314 g
->canCallOS
= false;
315 ++g
->sp
; SetObject(g
->sp
, m_obj
);
316 ++g
->sp
; SetInt(g
->sp
, evt
.type
);
317 ++g
->sp
; SetInt(g
->sp
, evt
.code
);
318 ++g
->sp
; SetInt(g
->sp
, evt
.value
);
319 runInterpreter(g
, s_handleEvent
, 4);
320 g
->canCallOS
= false;
322 pthread_mutex_unlock(&gLangMutex
);
326 void SC_LID::readError(boost::atomic
<bool> const & shouldBeRunning
)
328 int status
= lockLanguageOrQuit(shouldBeRunning
);
332 postfl("error when locking language (%d)\n", status
);
337 VMGlobals
* g
= gMainVMGlobals
;
338 g
->canCallOS
= false;
339 ++g
->sp
; SetObject(g
->sp
, m_obj
);
340 runInterpreter(g
, s_readError
, 1);
341 g
->canCallOS
= false;
343 pthread_mutex_unlock(&gLangMutex
);
346 // =====================================================================
349 SC_LIDManager
& SC_LIDManager::instance()
351 static SC_LIDManager instance
;
355 SC_LIDManager::SC_LIDManager()
359 if (pipe(m_cmdFifo
) == -1) {
360 m_cmdFifo
[0] = m_cmdFifo
[1] = -1;
365 SC_LIDManager::~SC_LIDManager()
371 int SC_LIDManager::start()
373 mShouldBeRunning
= true;
374 int err
= pthread_create(&m_thread
, 0, &threadFunc
, this);
375 if (err
!= 0) return errFailed
;
379 int SC_LIDManager::stop()
381 if (m_running
== false)
387 int err
= sendCommand(cmd
);
390 mShouldBeRunning
= false;
391 err
= pthread_join(m_thread
, 0);
392 if (err
!= 0) return errFailed
;
397 int SC_LIDManager::add(SC_LID
* dev
)
402 return sendCommand(cmd
);
405 int SC_LIDManager::remove(SC_LID
* dev
)
410 return sendCommand(cmd
);
413 int SC_LIDManager::sendCommand(const Command
& cmd
)
415 return write(m_cmdFifo
[1], &cmd
, sizeof(cmd
)) == sizeof(cmd
) ? errNone
: errFailed
;
418 void SC_LIDManager::devicesChanged()
420 int fdMax
= m_cmdFifo
[0];
423 FD_SET(fdMax
, &m_fds
);
425 SC_LID
*dev
= m_devices
;
430 if (fd
> fdMax
) fdMax
= fd
;
438 bool SC_LIDManager::asyncAddDevice(SC_LID
* dev
)
440 if (dev
->m_next
) return false;
441 dev
->m_next
= m_devices
;
447 bool SC_LIDManager::asyncRemoveDevice(SC_LID
* dev
)
449 SC_LID
*prev
= 0, *cur
= m_devices
;
453 if (prev
) prev
->m_next
= dev
->m_next
;
454 else m_devices
= dev
->m_next
;
467 void* SC_LIDManager::threadFunc(void* arg
)
469 ((SC_LIDManager
*)arg
)->loop();
473 void SC_LIDManager::loop()
476 post("LID: event loop started\n");
480 memcpy(&fds
, &m_fds
, sizeof(fd_set
));
481 int n
= select(m_nfds
, &fds
, 0, 0, 0);
483 if( errno
== EINTR
) continue;
484 post("LID: error in input handler: %s\n", strerror(errno
));
487 if (FD_ISSET(m_cmdFifo
[0], &fds
)) {
490 int err
= read(m_cmdFifo
[0], &cmd
, sizeof(cmd
));
492 if( errno
!= EINTR
) {
493 post("LID: error in input handler: %s\n", strerror(errno
));
502 if (asyncAddDevice(cmd
.arg
.dev
)) {
503 post("LID: added device %p\n", cmd
.arg
);
505 post("LID: cannot add device\n");
509 if (asyncRemoveDevice(cmd
.arg
.dev
)) {
510 post("LID: removed device %p\n", cmd
.arg
);
512 post("LID: couldn't remove device\n");
516 post("LID: unknown command in input handler\n");
521 SC_LID
*dev
= m_devices
;
524 if (FD_ISSET(fd
, &fds
)) {
525 struct input_event evt
;
526 if (read(fd
, &evt
, sizeof(evt
)) == sizeof(evt
)) {
527 dev
->handleEvent(evt
, mShouldBeRunning
);
530 dev
->readError(mShouldBeRunning
);
533 if (!mShouldBeRunning
)
543 post("LID: event loop stopped\n");
546 // =====================================================================
547 // Primitive Interface
549 int prLID_Open(VMGlobals
*g
, int numArgsPushed
)
551 PyrSlot
* args
= g
->sp
- 1;
554 PyrObject
* obj
= SC_LID::getObject(args
+0);
555 if (!obj
) return errWrongType
;
558 err
= slotStrVal(args
+1, path
, sizeof(path
));
561 SC_LID
* dev
= new SC_LID(obj
);
562 err
= dev
->open(path
);
571 int prLID_Close(VMGlobals
*g
, int numArgsPushed
)
573 PyrSlot
* args
= g
->sp
;
575 PyrObject
* obj
= SC_LID::getObject(args
+0);
576 if (!obj
) return errWrongType
;
578 SC_LID
* dev
= SC_LID::getDevice(obj
);
579 if (!dev
) return errFailed
;
584 int prLID_EventTypeSupported(VMGlobals
*g
, int numArgsPushed
)
586 PyrSlot
* args
= g
->sp
- 1;
590 if (!g
->canCallOS
) return errCantCallOS
;
592 PyrObject
* obj
= SC_LID::getObject(args
+0);
593 if (!obj
) return errWrongType
;
595 err
= slotIntVal(args
+1, &evtType
);
598 SC_LID
* dev
= SC_LID::getDevice(obj
);
599 if (!dev
) return errFailed
;
601 SetBool(args
, dev
->isEventTypeSupported(evtType
));
606 int prLID_EventCodeSupported(VMGlobals
*g
, int numArgsPushed
)
608 PyrSlot
* args
= g
->sp
- 2;
609 int evtType
, evtCode
;
612 if (!g
->canCallOS
) return errCantCallOS
;
614 PyrObject
* obj
= SC_LID::getObject(args
+0);
615 if (!obj
) return errWrongType
;
617 err
= slotIntVal(args
+1, &evtType
);
620 err
= slotIntVal(args
+2, &evtCode
);
623 SC_LID
* dev
= SC_LID::getDevice(obj
);
624 if (!dev
) return errFailed
;
626 SetBool(args
, dev
->isEventCodeSupported(evtType
, evtCode
));
631 int prLID_GetInfo(VMGlobals
* g
, int numArgsPushed
)
633 PyrSlot
* args
= g
->sp
- 1;
636 PyrObject
* obj
= SC_LID::getObject(args
+0);
637 if (!obj
) return errWrongType
;
639 if (!isKindOfSlot(args
+1, s_inputDeviceInfoClass
->u
.classobj
))
641 PyrObject
* infoObj
= slotRawObject(&args
[1]);
643 SC_LID
* dev
= SC_LID::getDevice(obj
);
644 if (!dev
) return errFailed
;
647 err
= dev
->getName(name
, sizeof(name
));
650 struct input_id info
;
653 err
= dev
->getInfo(&info
, namePhys
, sizeof( namePhys
), nameUniq
, sizeof( nameUniq
) );
656 SetSymbol(infoObj
->slots
+0, getsym(name
));
657 SetInt(infoObj
->slots
+1, info
.bustype
);
658 SetInt(infoObj
->slots
+2, info
.vendor
);
659 SetInt(infoObj
->slots
+3, info
.product
);
660 SetInt(infoObj
->slots
+4, info
.version
);
661 SetSymbol(infoObj
->slots
+5, getsym(namePhys
));
662 SetSymbol(infoObj
->slots
+6, getsym(nameUniq
));
664 slotCopy(&args
[0], &args
[1]);
669 int prLID_GetKeyState(VMGlobals
*g
, int numArgsPushed
)
671 PyrSlot
* args
= g
->sp
- 1;
675 PyrObject
* obj
= SC_LID::getObject(args
+0);
676 if (!obj
) return errWrongType
;
678 err
= slotIntVal(args
+1, &evtCode
);
681 SC_LID
* dev
= SC_LID::getDevice(obj
);
682 if (!dev
) return errFailed
;
684 SetInt(args
, dev
->getKeyState(evtCode
));
689 int prLID_GetAbsInfo(VMGlobals
*g
, int numArgsPushed
)
691 PyrSlot
* args
= g
->sp
- 2;
695 PyrObject
* obj
= SC_LID::getObject(args
+0);
696 if (!obj
) return errWrongType
;
698 err
= slotIntVal(args
+1, &evtCode
);
701 if (!isKindOfSlot(args
+2, s_absInfoClass
->u
.classobj
))
703 PyrObject
* infoObj
= slotRawObject(&args
[2]);
705 SC_LID
* dev
= SC_LID::getDevice(obj
);
706 if (!dev
) return errFailed
;
708 struct input_absinfo info
;
709 err
= dev
->getAbsInfo(evtCode
, &info
);
712 SetInt(infoObj
->slots
+0, info
.value
);
713 SetInt(infoObj
->slots
+1, info
.minimum
);
714 SetInt(infoObj
->slots
+2, info
.maximum
);
715 SetInt(infoObj
->slots
+3, info
.fuzz
);
716 SetInt(infoObj
->slots
+4, info
.flat
);
718 slotCopy(&args
[0], &args
[2]);
723 int prLID_Grab(VMGlobals
*g
, int numArgsPushed
)
725 PyrSlot
* args
= g
->sp
- 1;
727 PyrObject
* obj
= SC_LID::getObject(args
+0);
728 if (!obj
) return errWrongType
;
730 SC_LID
* dev
= SC_LID::getDevice(obj
);
731 if (!dev
) return errFailed
;
733 return dev
->grab(IsTrue(args
+1));
736 int prLID_Start(VMGlobals
* g
, int numArgsPushed
)
738 // if (!g->canCallOS) return errCantCallOS;
739 return SC_LIDManager::instance().start();
742 int prLID_Stop(VMGlobals
* g
, int numArgsPushed
)
744 // if (!g->canCallOS) return errCantCallOS;
745 return SC_LIDManager::instance().stop();
748 int prLID_SetLedState(VMGlobals
*g
, int numArgsPushed
)
750 // post( "set led state primitive called" );
751 PyrSlot
* args
= g
->sp
- 2;
752 int evtCode
, evtValue
;
755 PyrObject
* obj
= SC_LID::getObject(args
+0);
756 if (!obj
) return errWrongType
;
758 err
= slotIntVal(args
+1, &evtCode
);
761 err
= slotIntVal(args
+2, &evtValue
);
764 SC_LID
* dev
= SC_LID::getDevice(obj
);
765 if (!dev
) return errFailed
;
767 SetInt(args
, dev
->setLedState(evtCode
,evtValue
, EV_LED
));
771 int prLID_SetMscState(VMGlobals
*g
, int numArgsPushed
)
773 // post( "set msc state primitive called\n" );
774 PyrSlot
* args
= g
->sp
- 2;
775 int evtCode
, evtValue
;
778 PyrObject
* obj
= SC_LID::getObject(args
+0);
779 if (!obj
) return errWrongType
;
781 err
= slotIntVal(args
+1, &evtCode
);
784 err
= slotIntVal(args
+2, &evtValue
);
787 SC_LID
* dev
= SC_LID::getDevice(obj
);
788 if (!dev
) return errFailed
;
790 SetInt(args
, dev
->setLedState(evtCode
,evtValue
, EV_MSC
));
798 s_inputDeviceClass
= getsym("LID");
799 s_inputDeviceInfoClass
= getsym("LIDInfo");
800 s_absInfoClass
= getsym("LIDAbsInfo");
801 s_handleEvent
= getsym("prHandleEvent");
802 s_readError
= getsym("prReadError");
804 base
= nextPrimitiveIndex();
807 definePrimitive(base
, index
++, "_LID_Open", prLID_Open
, 2, 0);
808 definePrimitive(base
, index
++, "_LID_Close", prLID_Close
, 1, 0);
809 definePrimitive(base
, index
++, "_LID_EventTypeSupported", prLID_EventTypeSupported
, 2, 0);
810 definePrimitive(base
, index
++, "_LID_EventCodeSupported", prLID_EventCodeSupported
, 3, 0);
811 definePrimitive(base
, index
++, "_LID_GetInfo", prLID_GetInfo
, 2, 0);
812 definePrimitive(base
, index
++, "_LID_GetKeyState", prLID_GetKeyState
, 2, 0);
813 definePrimitive(base
, index
++, "_LID_GetAbsInfo", prLID_GetAbsInfo
, 3, 0);
814 definePrimitive(base
, index
++, "_LID_Grab", prLID_Grab
, 2, 0);
815 definePrimitive(base
, index
++, "_LID_Start", prLID_Start
, 1, 0);
816 definePrimitive(base
, index
++, "_LID_Stop", prLID_Stop
, 1, 0);
817 definePrimitive(base
, index
++, "_LID_SetLedState", prLID_SetLedState
, 3, 0); // added by Marije Baalman
818 definePrimitive(base
, index
++, "_LID_SetMscState", prLID_SetMscState
, 3, 0);
821 int prLID_Start(VMGlobals
* g
, int numArgsPushed
)
826 int prLID_Stop(VMGlobals
* g
, int numArgsPushed
)
835 base
= nextPrimitiveIndex();
838 definePrimitive(base
, index
++, "_LID_Start", prLID_Start
, 1, 0);
839 definePrimitive(base
, index
++, "_LID_Stop", prLID_Stop
, 1, 0);
843 void initHIDPrimitives()