diff options
author | Hans-Christoph Steiner <eighthave@users.sourceforge.net> | 2004-10-22 05:43:17 +0000 |
---|---|---|
committer | Hans-Christoph Steiner <eighthave@users.sourceforge.net> | 2004-10-22 05:43:17 +0000 |
commit | f59333ff17f17d8fa9e983ccee47f43cd77a3040 (patch) | |
tree | 70d61e79f5bf94dde7f67621e8e7bd6f946f1cff | |
parent | 80bdb3696f585bd27168675a2cea0bc13b60b350 (diff) |
started the process of organizing things for cross-platformness; sketched out MacOS X HID Manager implementation using SuperCollider3's SC_HID.cpp
svn path=/trunk/externals/hcs/hid/; revision=2140
-rw-r--r-- | hid.c | 79 | ||||
-rw-r--r-- | hid.h | 26 | ||||
-rw-r--r-- | hid_darwin.c | 463 |
3 files changed, 505 insertions, 63 deletions
@@ -25,59 +25,8 @@ /* */ /* ---------------------------------------------------------------------------- */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <ctype.h> - -#ifdef __APPLE__ -#include <sys/errno.h> -#include <sysexits.h> -#include <mach/mach.h> -#include <mach/mach_error.h> -#include <IOKit/IOKitLib.h> -#include <IOKit/IOCFPlugIn.h> -#include <IOKit/hid/IOHIDLib.h> -#include <IOKit/hid/IOHIDKeys.h> -#include <IOKit/hid/IOHIDUsageTables.h> -#include <CoreFoundation/CoreFoundation.h> -#include <Carbon/Carbon.h> - -#ifndef __APPLE_CC__ -#include "Carbon_Include.h" -#endif /* #ifndef __APPLE_CC__ */ - -#include <HID_Utilities.h> -#endif /* #ifdef __APPLE__ */ - -#include "linuxhid.h" -#include "input_arrays.h" - -static char *version = "$Revision: 1.3 $"; - -/*------------------------------------------------------------------------------ - * CLASS DEF - */ -static t_class *hid_class; - -typedef struct _hid -{ - t_object x_obj; - t_int x_fd; - t_symbol *x_devname; - t_clock *x_clock; - t_int x_read_ok; - t_int x_started; - t_int x_delay; -#ifdef __gnu_linux__ - struct input_event x_input_event; -#elif defined (__APPLE__) - IOHIDEventStruct event; -#endif - t_outlet *x_event_outlet; -}t_hid; - +#include "hid.h" +#include "../linuxhid.h" /*------------------------------------------------------------------------------ * IMPLEMENTATION @@ -113,6 +62,9 @@ static t_int hid_open(t_hid *x, t_symbol *s) { t_int eventType, eventCode; char *eventTypeName = ""; +#ifdef __linux__ + struct input_event hid_input_event; +#endif /* counts for various event types */ t_int synCount,keyCount,relCount,absCount,mscCount,ledCount,sndCount,repCount,ffCount,pwrCount,ff_statusCount; #ifdef __gnu_linux__ @@ -147,7 +99,7 @@ static t_int hid_open(t_hid *x, t_symbol *s) /* read input_events from the HID_DEVICE stream * It seems that is just there to flush the input event queue */ - while (read (x->x_fd, &(x->x_input_event), sizeof(struct input_event)) > -1); + while (read (x->x_fd, &(hid_input_event), sizeof(struct input_event)) > -1); /* get name of device */ ioctl(x->x_fd, EVIOCGNAME(sizeof(devicename)), devicename); @@ -251,24 +203,25 @@ static t_int hid_read(t_hid *x,int fd) t_atom event_data[5]; char *eventType; char *eventCode; +#ifdef __linux__ + struct input_event hid_input_event; -#ifdef __gnu_linux__ if (x->x_fd < 0) return 0; - while (read (x->x_fd, &(x->x_input_event), sizeof(struct input_event)) > -1) + while (read (x->x_fd, &(hid_input_event), sizeof(struct input_event)) > -1) { /* build event_data list from event data */ - SETSYMBOL(event_data, gensym(ev[x->x_input_event.type])); - SETSYMBOL(event_data + 1, gensym(event_names[x->x_input_event.type][x->x_input_event.code])); - SETFLOAT(event_data + 2, (t_float)x->x_input_event.value); - SETFLOAT(event_data + 3, (t_float)(x->x_input_event.time).tv_sec); + SETSYMBOL(event_data, gensym(ev[hid_input_event.type])); + SETSYMBOL(event_data + 1, gensym(event_names[hid_input_event.type][hid_input_event.code])); + SETFLOAT(event_data + 2, (t_float)hid_input_event.value); + SETFLOAT(event_data + 3, (t_float)(hid_input_event.time).tv_sec); outlet_anything(x->x_obj.te_outlet,atom_gensym(event_data),3,event_data+1); } #endif /* #ifdef__gnu_linux__ */ -#ifdef __APPLE__ +#ifdef IGNOREIGNOREIGNORE pRecDevice pCurrentHIDDevice = GetSetCurrentDevice (gWindow); pRecElement pCurrentHIDElement = GetSetCurrenstElement (gWindow); - r/l + // if we have a good device and element which is not a collecion if (pCurrentHIDDevice && pCurrentHIDElement && (pCurrentHIDElement->type != kIOHIDElementTypeCollection)) { @@ -364,7 +317,7 @@ static void *hid_new(t_symbol *s) x->x_clock = clock_new(x, (t_method)hid_read); - /* create anything outlet */ + /* create anything outlet used for HID data */ outlet_new(&x->x_obj, 0); /* set to the value from the object argument, if that exists */ @@ -0,0 +1,26 @@ + +#include <m_pd.h> + +#include "input_arrays.h" + +static char *version = "$Revision: 1.1 $"; + +/*------------------------------------------------------------------------------ + * CLASS DEF + */ +static t_class *hid_class; + +typedef struct _hid +{ + t_object x_obj; + t_int x_fd; + t_symbol *x_devname; + t_clock *x_clock; + t_int x_read_ok; + t_int x_started; + t_int x_delay; + t_int x_vendorID; + t_int x_productID; + t_int x_locID; +} t_hid; + diff --git a/hid_darwin.c b/hid_darwin.c new file mode 100644 index 0000000..dc84ae2 --- /dev/null +++ b/hid_darwin.c @@ -0,0 +1,463 @@ +/* + * Apple Darwin HID Manager support for [hid] + * + * based on SC_HID.cpp from SuperCollider3 by Jan Truetzschler v. Falkenstein + * + * Copyright (c) 2004 Hans-Christoph All rights reserved. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + */ +#include <Carbon/Carbon.h> + +#include "HID_Utilities_External.h" + +/* +#include <IOKit/IOKitLib.h> +#include <IOKit/IOCFPlugIn.h> +#include <IOKit/hid/IOHIDLib.h> +#include <IOKit/hid/IOHIDKeys.h> +*/ +#include <IOKit/hid/IOHIDUsageTables.h> + +#include <mach/mach.h> +#include <mach/mach_error.h> + +#include "hid.h" + +/* +#include "SCBase.h" +#include "VMGlobals.h" +#include "PyrSymbolTable.h" +#include "PyrInterpreter.h" +#include "PyrKernel.h" + +#include "PyrObjectProto.h" +#include "PyrPrimitiveProto.h" +#include "PyrKernelProto.h" +#include "SC_InlineUnaryOp.h" +#include "SC_InlineBinaryOp.h" +#include "PyrSched.h" +#include "GC.h" +*/ + +int gNumberOfHIDDevices = 0; +EventLoopTimerRef gTimer = NULL; // timer for element data updates + + +void releaseHIDDevices () +{ + if (gTimer) + { + RemoveEventLoopTimer(gTimer); + gTimer = NULL; + } + HIDReleaseAllDeviceQueues(); + HIDReleaseDeviceList(); + gNumberOfHIDDevices = 0; +} + +int prHIDBuildElementList() +{ +/* + PyrSlot *a = g->sp - 1; //class + PyrSlot *b = g->sp; //locID device +*/ + int i, locID, cookieNum; + pRecElement devElement; + pRecDevice pCurrentHIDDevice; +// int err; + +// int err = slotIntVal(b, &locID); +// if (err) return err; + + // look for the right device: + pCurrentHIDDevice = HIDGetFirstDevice (); + while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID)) + pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice); + if(!pCurrentHIDDevice) return (1); + + devElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeInput); + UInt32 numElements = HIDCountDeviceElements (pCurrentHIDDevice, kHIDElementTypeInput); + + //PyrObject* devAllElementsArray = newPyrArray(g->gc, numElements * sizeof(PyrObject), 0 , true); + + for(i=0; i<numElements; i++) + { + char cstrElementName [256]; + //PyrObject* devElementArray = newPyrArray(g->gc, 5 * sizeof(PyrObject), 0 , true); + HIDGetTypeName((IOHIDElementType) devElement->type, cstrElementName); + //PyrString *devstring = newPyrString(g->gc, cstrElementName, 0, true); + //SetObject(devElementArray->slots+devElementArray->size++, devstring); + //g->gc->GCWrite(devElementArray, (PyrObject*) devstring); + //usage + HIDGetUsageName (devElement->usagePage, devElement->usage, cstrElementName); + //devstring = newPyrString(g->gc, cstrElementName, 0, true); + //SetObject(devElementArray->slots+devElementArray->size++, devstring); + //g->gc->GCWrite(devElementArray, (PyrObject*) devstring); + //cookie + //SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->cookie); + //SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->min); + //SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->max); + + //SetObject(devAllElementsArray->slots+devAllElementsArray->size++, devElementArray); + //g->gc->GCWrite(devAllElementsArray, (PyrObject*) devElementArray); + + devElement = HIDGetNextDeviceElement (devElement, kHIDElementTypeInput); + } + //SetObject(a, devAllElementsArray); + + return (0); +} + +int prHIDBuildDeviceList() +{ + int i,err; + UInt32 usagePage, usage; +/* + //build a device list + PyrSlot *a = g->sp - 2; + PyrSlot *b = g->sp - 1; //usagePage + PyrSlot *c = g->sp; //usage + + if(IsNil(b)) + usagePage = NULL; + else + { + err = slotIntVal(b, &usagePage); + if (err) return err; + } + if(IsNil(c)) + usage = NULL; + else + { + err = slotIntVal(c, &usage); + if (err) return err; + } + + //pass in usage & usagepage + //kHIDUsage_GD_Joystick kHIDUsage_GD_GamePad + */ + usagePage = kHIDPage_GenericDesktop; + usage = NULL; + + Boolean result = HIDBuildDeviceList (usagePage, usage); + // returns false if no device found (ignored in this case) - returns always false ? + + if(result) post("no HID devices found\n"); + + int numdevs = HIDCountDevices(); + gNumberOfHIDDevices = numdevs; + // exit if no devices found + if(!numdevs) return (0); + + post("number of devices: %d", numdevs); + char cstrDeviceName [256]; + + pRecDevice pCurrentHIDDevice = HIDGetFirstDevice (); + pRecElement devElement; + //PyrObject* allDevsArray = newPyrArray(g->gc, numdevs * sizeof(PyrObject), 0 , true); + for(i=0; i<numdevs; i++) + { + /* + //device: + /PyrObject* devNameArray = newPyrArray(g->gc, 6 * sizeof(PyrObject), 0 , true); + //manufacturer: + PyrString *devstring = newPyrString(g->gc, pCurrentHIDDevice->manufacturer, 0, true); + SetObject(devNameArray->slots+devNameArray->size++, devstring); + g->gc->GCWrite(devNameArray, (PyrObject*) devstring); + //product name: + devstring = newPyrString(g->gc, pCurrentHIDDevice->product, 0, true); + SetObject(devNameArray->slots+devNameArray->size++, devstring); + g->gc->GCWrite(devNameArray, (PyrObject*) devstring); + */ + //usage + HIDGetUsageName (pCurrentHIDDevice->usagePage, pCurrentHIDDevice->usage, cstrDeviceName); + /* + devstring = newPyrString(g->gc, cstrDeviceName, 0, true); + SetObject(devNameArray->slots+devNameArray->size++, devstring); + g->gc->GCWrite(devNameArray, (PyrObject*) devstring); + //vendor id + SetInt(devNameArray->slots+devNameArray->size++, pCurrentHIDDevice->vendorID); + //product id + SetInt(devNameArray->slots+devNameArray->size++, pCurrentHIDDevice->productID); + //locID + SetInt(devNameArray->slots+devNameArray->size++, pCurrentHIDDevice->locID); + + SetObject(allDevsArray->slots+allDevsArray->size++, devNameArray); + g->gc->GCWrite(allDevsArray, (PyrObject*) devNameArray); + */ + pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice); + + } + + //UInt32 outnum = HIDCountDeviceElements (pCurrentHIDDevice, kHIDElementTypeOutput); + //post("number of outputs: %d \n", outnum); +// SetObject(a, allDevsArray); + + return (0); +} + +/* +int prHIDGetValue(VMGlobals *g); +int prHIDGetValue(VMGlobals *g) +{ + PyrSlot *a = g->sp - 2; //class + PyrSlot *b = g->sp - 1; //locID device + PyrSlot *c = g->sp; //element cookie + int locID, cookieNum; + int err = slotIntVal(b, &locID); + if (err) return err; + err = slotIntVal(c, &cookieNum); + if (err) return err; + IOHIDElementCookie cookie = (IOHIDElementCookie) cookieNum; + // look for the right device: + pRecDevice pCurrentHIDDevice = HIDGetFirstDevice (); + while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID)) + pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice); + if(!pCurrentHIDDevice) return (1); + // look for the right element: + pRecElement pCurrentHIDElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeIO); + // use gElementCookie to find current element + while (pCurrentHIDElement && (pCurrentHIDElement->cookie != cookie)) + pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeIO); + + if (pCurrentHIDElement) + { + SInt32 value = HIDGetElementValue (pCurrentHIDDevice, pCurrentHIDElement); + // if it's not a button and it's not a hatswitch then calibrate + if(( pCurrentHIDElement->type != kIOHIDElementTypeInput_Button ) && + ( pCurrentHIDElement->usagePage == 0x01 && pCurrentHIDElement->usage != kHIDUsage_GD_Hatswitch)) + value = HIDCalibrateValue ( value, pCurrentHIDElement ); + SetInt(a, value); + } + else SetNil(a); + return (0); + +} +*/ +void PushQueueEvents_RawValue () +{ + int i; + + IOHIDEventStruct event; + pRecDevice pCurrentHIDDevice = HIDGetFirstDevice (); + int numdevs = gNumberOfHIDDevices; + unsigned char result; + for(i=0; i< numdevs; i++) + { + result = HIDGetEvent(pCurrentHIDDevice, (void*) &event); + if(result) + { + SInt32 value = event.value; + int vendorID = pCurrentHIDDevice->vendorID; + int productID = pCurrentHIDDevice->productID; + int locID = pCurrentHIDDevice->locID; + IOHIDElementCookie cookie = (IOHIDElementCookie) event.elementCookie; + //set arguments: +// ++g->sp;SetInt(g->sp, vendorID); +// ++g->sp;SetInt(g->sp, productID); +// ++g->sp;SetInt(g->sp, locID); +// ++g->sp;SetInt(g->sp, (int) cookie); +// ++g->sp;SetInt(g->sp, value); + } + pCurrentHIDDevice = HIDGetNextDevice(pCurrentHIDDevice); + } +} + +void PushQueueEvents_CalibratedValue () +{ + int i; + + IOHIDEventStruct event; + pRecDevice pCurrentHIDDevice = HIDGetFirstDevice (); + + int numdevs = gNumberOfHIDDevices; + unsigned char result; + for(i=0; i< numdevs; i++) + { + + result = HIDGetEvent(pCurrentHIDDevice, (void*) &event); + if(result) + { + SInt32 value = event.value; + int vendorID = pCurrentHIDDevice->vendorID; + int productID = pCurrentHIDDevice->productID; + int locID = pCurrentHIDDevice->locID; + IOHIDElementCookie cookie = (IOHIDElementCookie) event.elementCookie; + pRecElement pCurrentHIDElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeIO); + // use gElementCookie to find current element + while (pCurrentHIDElement && ( (pCurrentHIDElement->cookie) != cookie)) + pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeIO); + + if (pCurrentHIDElement) + { + value = HIDCalibrateValue(value, pCurrentHIDElement); + //find element to calibrate + //set arguments: +// ++g->sp;SetInt(g->sp, vendorID); +// ++g->sp;SetInt(g->sp, productID); +// ++g->sp;SetInt(g->sp, locID); +// ++g->sp;SetInt(g->sp, (int) cookie); +// ++g->sp;SetInt(g->sp, value); + } + } + pCurrentHIDDevice = HIDGetNextDevice(pCurrentHIDDevice); + } +} + +static pascal void IdleTimer (EventLoopTimerRef inTimer, void* userData) +{ + #pragma unused (inTimer, userData) + PushQueueEvents_CalibratedValue (); +} + +int prHIDReleaseDeviceList() +{ + releaseHIDDevices(); + return (0); +} + +static EventLoopTimerUPP GetTimerUPP (void) +{ + static EventLoopTimerUPP sTimerUPP = NULL; + + if (sTimerUPP == NULL) + sTimerUPP = NewEventLoopTimerUPP (IdleTimer); + + return sTimerUPP; +} +/* +typedef void (*IOHIDCallbackFunction) + (void * target, IOReturn result, void * refcon, void * sender); + +*/ +/* +void callback (void * target, IOReturn result, void * refcon, void * sender); +void callback (void * target, IOReturn result, void * refcon, void * sender) +{ +} +*/ +/* +int prHIDRunEventLoop(VMGlobals *g); +int prHIDRunEventLoop(VMGlobals *g) +{ + PyrSlot *a = g->sp - 1; //class + + InstallEventLoopTimer (GetCurrentEventLoop(), 0, 0.001, GetTimerUPP (), 0, &gTimer); + + //HIDSetQueueCallback(pCurrentHIDDevice, callback); + return (0); +} +*/ + +int prHIDQueueDevice() +{ + int locID, cookieNum; + + //PyrSlot *a = g->sp - 1; //class + //PyrSlot *b = g->sp; //locID device + //int err = slotIntVal(b, &locID); + //if (err) return err; + //look for the right device: + pRecDevice pCurrentHIDDevice = HIDGetFirstDevice (); + while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID)) + pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice); + if(!pCurrentHIDDevice) return (1); + HIDQueueDevice(pCurrentHIDDevice); + return (0); +} + +int prHIDQueueElement() +{ + int locID, cookieNum; + + //PyrSlot *a = g->sp - 2; //class + //PyrSlot *b = g->sp - 1; //locID device + //PyrSlot *c = g->sp; //element cookie + //int err = slotIntVal(b, &locID); + //if (err) return err; + //err = slotIntVal(c, &cookieNum); + //if (err) return err; + IOHIDElementCookie cookie = (IOHIDElementCookie) cookieNum; + //look for the right device: + pRecDevice pCurrentHIDDevice = HIDGetFirstDevice (); + while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID)) + pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice); + if(!pCurrentHIDDevice) return (1); + //look for the right element: + pRecElement pCurrentHIDElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeIO); + // use gElementCookie to find current element + while (pCurrentHIDElement && (pCurrentHIDElement->cookie != cookie)) + pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeIO); + if(!pCurrentHIDElement) return (1); + HIDQueueElement(pCurrentHIDDevice, pCurrentHIDElement); + return (0); +} + +int prHIDDequeueElement() +{ + int locID, cookieNum; + + //PyrSlot *a = g->sp - 2; //class + //PyrSlot *b = g->sp - 1; //locID device + //PyrSlot *c = g->sp; //element cookie + //int err = slotIntVal(b, &locID); + //if (err) return err; + //err = slotIntVal(c, &cookieNum); + //if (err) return err; + IOHIDElementCookie cookie = (IOHIDElementCookie) cookieNum; + //look for the right device: + pRecDevice pCurrentHIDDevice = HIDGetFirstDevice (); + while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID)) + pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice); + if(!pCurrentHIDDevice) return (1); + //look for the right element: + pRecElement pCurrentHIDElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeIO); + while (pCurrentHIDElement && (pCurrentHIDElement->cookie != cookie)) + pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeIO); + if(!pCurrentHIDElement) return (1); + HIDDequeueElement(pCurrentHIDDevice, pCurrentHIDElement); + return (0); +} + +int prHIDDequeueDevice() +{ + int locID, cookieNum; + + /* + PyrSlot *a = g->sp - 1; //class + PyrSlot *b = g->sp; //locID device + int err = slotIntVal(b, &locID); + if (err) return err; + */ + //look for the right device: + pRecDevice pCurrentHIDDevice = HIDGetFirstDevice (); + while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID)) + pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice); + if(!pCurrentHIDDevice) return (1); + HIDDequeueDevice(pCurrentHIDDevice); + return (0); +} + +int prHIDStopEventLoop() +{ + if (gTimer) + RemoveEventLoopTimer(gTimer); + gTimer = NULL; + return (0); +} + + |