bumping version to 3.5-rc1
[supercollider.git] / lang / LangPrimSource / SC_HID.cpp
blob5a3d137e44f541fde0b95a70b76263e151bf1d21
1 /*
2 * SC_HID.cpp
3 * SC3lang
5 * Created by Jan Truetzschler v. Falkenstein on Tue Sep 30 2003.
6 * Copyright (c) 2003 jan.t. All rights reserved.
7 * modifications by Marije Baalman in May 2007
8 * part of ...
9 SuperCollider real time audio synthesis system
10 Copyright (c) 2002 James McCartney. All rights reserved.
11 http://www.audiosynth.com
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 #ifdef SC_DARWIN
30 #include <Carbon/Carbon.h>
32 #include "HID_Utilities_External.h"
35 #include <IOKit/IOKitLib.h>
36 #include <IOKit/IOCFPlugIn.h>
37 #include <IOKit/hid/IOHIDLib.h>
38 #include <IOKit/hid/IOHIDKeys.h>
40 #include <IOKit/hid/IOHIDUsageTables.h>
42 #include <mach/mach.h>
43 #include <mach/mach_error.h>
44 #include "SCBase.h"
45 #include "VMGlobals.h"
46 #include "PyrSymbolTable.h"
47 #include "PyrInterpreter.h"
48 #include "PyrKernel.h"
50 #include "PyrObjectProto.h"
51 #include "PyrPrimitiveProto.h"
52 #include "PyrKernelProto.h"
53 #include "SC_InlineUnaryOp.h"
54 #include "SC_InlineBinaryOp.h"
55 #include "PyrSched.h"
56 #include "GC.h"
58 // Backward compatibility for the older (10.4) way of doing things:
59 #if (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4)
60 #define SC_MAC_HIDSTYLE_10_4 1
61 #define IOHIDDeviceRef pRecDevice
62 #define IOHIDElementRef pRecElement
63 #define IOHIDDevice_GetLocationID(x) (x->locID)
64 #define IOHIDElementGetType(x) ((IOHIDElementType) x->type)
65 #define IOHIDElementGetCookie(x) (x->cookie)
66 #define IOHIDElementGetLogicalMin(x) (x->min)
67 #define IOHIDElementGetLogicalMax(x) (x->max)
68 #define IOHIDElementGetUsagePage(x) (x->usagePage)
69 #define IOHIDElementGetUsage(x) (x->usage)
70 #define IOHIDDevice_GetManufacturer(x) (x->manufacturer)
71 #define IOHIDDevice_GetProduct(x) (x->product)
72 #define IOHIDDevice_GetUsagePage(x) (x->usagePage)
73 #define IOHIDDevice_GetUsage(x) (x->usage)
74 #define IOHIDDevice_GetVendorID(x) (x->vendorID)
75 #define IOHIDDevice_GetProductID(x) (x->productID)
76 #define IOHIDDevice_GetLocationID(x) (x->locID)
77 #define IOHIDDevice_GetVersionNumber(x) (x->version)
78 #define IOHIDDevice_GetSerialNumber(x) (x->serial)
79 #endif
81 PyrSymbol * s_readError;
82 PyrSymbol * s_hidAction;
83 PyrSymbol * s_hid;
84 extern bool compiledOK;
85 int gNumberOfHIDDevices = 0;
86 EventLoopTimerRef gTimer = NULL; // timer for element data updates
88 void releaseHIDDevices ();
89 void releaseHIDDevices ()
91 if (gTimer)
93 RemoveEventLoopTimer(gTimer);
94 gTimer = NULL;
96 HIDReleaseAllDeviceQueues();
97 HIDReleaseDeviceList();
98 gNumberOfHIDDevices = 0;
101 int prHIDGetElementListSize(VMGlobals *g, int numArgsPushed);
102 int prHIDGetElementListSize(VMGlobals *g, int numArgsPushed)
104 PyrSlot *a = g->sp - 1; //class
105 PyrSlot *b = g->sp; //locID device
106 int locID;
107 int err = slotIntVal(b, &locID);
108 if (err) return err;
109 IOHIDDeviceRef pCurrentHIDDevice = HIDGetFirstDevice ();
110 while (pCurrentHIDDevice && (IOHIDDevice_GetLocationID(pCurrentHIDDevice) !=locID))
111 pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);
112 if(!pCurrentHIDDevice) return errFailed;
113 UInt32 numElements = HIDCountDeviceElements (pCurrentHIDDevice, kHIDElementTypeAll );
114 SetInt(a, numElements);
115 return errNone;
118 int prHIDBuildElementList(VMGlobals *g, int numArgsPushed);
119 int prHIDBuildElementList(VMGlobals *g, int numArgsPushed)
122 PyrSlot *a = g->sp - 2; //class
123 PyrSlot *b = g->sp - 1; //locID device
124 PyrSlot *c = g->sp; //array
126 int locID;
127 int err = slotIntVal(b, &locID);
128 if (err) return err;
129 //look for the right device:
130 IOHIDDeviceRef pCurrentHIDDevice = HIDGetFirstDevice ();
131 while (pCurrentHIDDevice && (IOHIDDevice_GetLocationID(pCurrentHIDDevice) !=locID))
132 pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);
133 if(!pCurrentHIDDevice) return errFailed;
135 IOHIDElementRef devElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeAll );
136 UInt32 numElements = HIDCountDeviceElements (pCurrentHIDDevice, kHIDElementTypeAll );
138 // PyrObject* devAllElementsArray = newPyrArray(g->gc, numElements * sizeof(PyrObject), 0 , true);
139 PyrObject *devAllElementsArray = slotRawObject(c);
140 // post("numElements: %d\n", numElements);
141 numElements = sc_clip(numElements, 0, devAllElementsArray->size);
142 for(uint i=0; i<numElements; i++){
143 if(devElement){
144 char cstrElementName [256];
145 PyrObject* devElementArray = newPyrArray(g->gc, 8 * sizeof(PyrObject), 0 , true);
146 // type name (1)
147 HIDGetTypeName(IOHIDElementGetType(devElement), cstrElementName);
148 PyrString *devstring = newPyrString(g->gc, cstrElementName, 0, true);
149 SetObject(devElementArray->slots+devElementArray->size++, devstring);
150 //g->gc->GCWrite(devElementArray, (PyrObject*) devstring);
151 //usage (2)
152 HIDGetUsageName (IOHIDElementGetUsagePage(devElement), IOHIDElementGetUsage(devElement), cstrElementName);
153 PyrString *usestring = newPyrString(g->gc, cstrElementName, 0, true);
154 SetObject(devElementArray->slots+devElementArray->size++, usestring);
155 //g->gc->GCWrite(devElementArray, (PyrObject*) usestring);
156 //cookie (3)
157 SetInt(devElementArray->slots+devElementArray->size++, (long) IOHIDElementGetCookie(devElement));
158 // min (4)
159 SetInt(devElementArray->slots+devElementArray->size++, (long) IOHIDElementGetLogicalMin(devElement));
160 // max (5)
161 SetInt(devElementArray->slots+devElementArray->size++, (long) IOHIDElementGetLogicalMax(devElement));
163 // IO type as int: (6)
164 SetInt(devElementArray->slots+devElementArray->size++, (int) IOHIDElementGetType(devElement));
165 // Usage page as int: (7)
166 SetInt(devElementArray->slots+devElementArray->size++, (long) IOHIDElementGetUsagePage(devElement));
167 // Usage type as int: (8)
168 SetInt(devElementArray->slots+devElementArray->size++, (long) IOHIDElementGetUsage(devElement));
170 SetObject(devAllElementsArray->slots+i, devElementArray);
171 //g->gc->GCWrite(devAllElementsArray, (PyrObject*) devElementArray);
173 devElement = HIDGetNextDeviceElement (devElement, kHIDElementTypeAll);
175 SetObject(a, devAllElementsArray);
176 return errNone;
181 int prHIDBuildDeviceList(VMGlobals *g, int numArgsPushed);
182 int prHIDBuildDeviceList(VMGlobals *g, int numArgsPushed)
184 //build a device list
185 PyrSlot *a = g->sp - 2;
186 PyrSlot *b = g->sp - 1; //usagePage
187 PyrSlot *c = g->sp; //usage
189 int usagePage, usage, err;
190 if(IsNil(b))
191 usagePage = 0;
192 else
194 err = slotIntVal(b, &usagePage);
195 if (err) return err;
197 if(IsNil(c))
198 usage = 0;
199 else
201 err = slotIntVal(c, &usage);
202 if (err) return err;
205 //pass in usage & usagepage
206 //kHIDUsage_GD_Joystick kHIDUsage_GD_GamePad
207 //UInt32 usagePage = kHIDPage_GenericDesktop;
208 //UInt32 usage = NULL;
210 Boolean result = HIDBuildDeviceList (usagePage, usage);
211 #if(SC_MAC_HIDSTYLE_10_4)
212 // on 10.4, this should return false (!)
213 result = !result;
214 #endif
215 if(!result) post("no HID devices found\n");
217 int numdevs = HIDCountDevices();
218 gNumberOfHIDDevices = numdevs;
219 if(!numdevs){
220 SetNil(a);
221 return errNone;
223 //post("number of devices: %d", numdevs);
225 IOHIDDeviceRef pCurrentHIDDevice = HIDGetFirstDevice ();
226 PyrObject* allDevsArray = newPyrArray(g->gc, numdevs * sizeof(PyrObject), 0 , true);
227 for(int i=0; i<numdevs; i++){
228 char tmp[256];
229 CFStringRef stringref;
230 //device:
231 PyrObject* devNameArray = newPyrArray(g->gc, 8 * sizeof(PyrObject), 0 , true);
232 //manufacturer:
233 #if(SC_MAC_HIDSTYLE_10_4)
234 PyrString *devstring = newPyrString(g->gc, pCurrentHIDDevice->manufacturer, 0, true);
235 #else
236 *tmp = 0;
237 stringref = IOHIDDevice_GetManufacturer(pCurrentHIDDevice);
238 if (stringref)
240 CFStringGetCString(stringref, tmp, 256, kCFStringEncodingASCII);
241 CFRelease(stringref);
243 PyrString *devstring = newPyrString(g->gc, tmp, 0, true);
244 #endif
245 SetObject(devNameArray->slots+devNameArray->size++, devstring);
246 g->gc->GCWrite(devNameArray, (PyrObject*) devstring);
247 //product name:
248 #if(SC_MAC_HIDSTYLE_10_4)
249 devstring = newPyrString(g->gc, pCurrentHIDDevice->product, 0, true);
250 #else
251 *tmp = 0;
252 stringref = IOHIDDevice_GetProduct(pCurrentHIDDevice);
253 if (stringref)
255 CFStringGetCString(stringref, tmp, 256, kCFStringEncodingASCII);
256 CFRelease(stringref);
258 devstring = newPyrString(g->gc, tmp, 0, true);
259 #endif
260 SetObject(devNameArray->slots+devNameArray->size++, devstring);
261 g->gc->GCWrite(devNameArray, (PyrObject*) devstring);
263 //usage
264 #if(SC_MAC_HIDSTYLE_10_4)
265 HIDGetUsageName (pCurrentHIDDevice->usagePage, pCurrentHIDDevice->usage, tmp);
266 devstring = newPyrString(g->gc, tmp, 0, true);
267 #else
268 *tmp = 0;
269 HIDGetUsageName (IOHIDDevice_GetPrimaryUsagePage(pCurrentHIDDevice), IOHIDDevice_GetPrimaryUsage(pCurrentHIDDevice), tmp);
270 devstring = newPyrString(g->gc, tmp, 0, true);
271 #endif
272 SetObject(devNameArray->slots+devNameArray->size++, devstring);
273 g->gc->GCWrite(devNameArray, (PyrObject*) devstring);
274 //vendor id
275 SetInt(devNameArray->slots+devNameArray->size++, IOHIDDevice_GetVendorID(pCurrentHIDDevice));
276 //product id
277 SetInt(devNameArray->slots+devNameArray->size++, IOHIDDevice_GetProductID(pCurrentHIDDevice));
278 //locID
279 SetInt(devNameArray->slots+devNameArray->size++, IOHIDDevice_GetLocationID(pCurrentHIDDevice));
281 //version
282 SetInt(devNameArray->slots+devNameArray->size++, IOHIDDevice_GetVersionNumber(pCurrentHIDDevice));
284 //serial
285 #if(SC_MAC_HIDSTYLE_10_4)
286 devstring = newPyrString(g->gc, pCurrentHIDDevice->serial, 0, true);
287 #else
288 *tmp = 0;
289 stringref = IOHIDDevice_GetSerialNumber(pCurrentHIDDevice);
290 if (stringref)
292 CFStringGetCString(stringref, tmp, 256, kCFStringEncodingASCII);
293 CFRelease(stringref);
295 devstring = newPyrString(g->gc, tmp, 0, true);
296 #endif
297 SetObject(devNameArray->slots+devNameArray->size++, devstring);
298 g->gc->GCWrite(devNameArray, (PyrObject*) devstring);
300 SetObject(allDevsArray->slots+allDevsArray->size++, devNameArray);
301 g->gc->GCWrite(allDevsArray, (PyrObject*) devNameArray);
302 pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);
306 //UInt32 outnum = HIDCountDeviceElements (pCurrentHIDDevice, kHIDElementTypeOutput);
307 //post("number of outputs: %d \n", outnum);
308 SetObject(a, allDevsArray);
310 return errNone;
314 int prHIDGetValue(VMGlobals *g, int numArgsPushed);
315 int prHIDGetValue(VMGlobals *g, int numArgsPushed)
317 PyrSlot *a = g->sp - 2; //class
318 PyrSlot *b = g->sp - 1; //locID device
319 PyrSlot *c = g->sp; //element cookie
320 int locID, cookieNum;
321 int err = slotIntVal(b, &locID);
322 if (err) return err;
323 err = slotIntVal(c, &cookieNum);
324 if (err) return err;
325 IOHIDElementCookie cookie = (IOHIDElementCookie) cookieNum;
326 //look for the right device:
327 IOHIDDeviceRef pCurrentHIDDevice = HIDGetFirstDevice ();
328 while (pCurrentHIDDevice && (IOHIDDevice_GetLocationID(pCurrentHIDDevice) !=locID))
329 pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);
330 if(!pCurrentHIDDevice) return errFailed;
331 //look for the right element:
332 IOHIDElementRef pCurrentHIDElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeAll);
333 // use gElementCookie to find current element
334 while (pCurrentHIDElement && (IOHIDElementGetCookie(pCurrentHIDElement) != cookie))
335 pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeAll);
337 if (pCurrentHIDElement)
339 #if(SC_MAC_HIDSTYLE_10_4)
340 SInt32 value = HIDGetElementValue (pCurrentHIDDevice, pCurrentHIDElement);
341 // if it's not a button and it's not a hatswitch then calibrate
342 if(( pCurrentHIDElement->type != kIOHIDElementTypeInput_Button ) &&
343 ( pCurrentHIDElement->usagePage == 0x01 && pCurrentHIDElement->usage != kHIDUsage_GD_Hatswitch))
344 value = HIDCalibrateValue ( value, pCurrentHIDElement );
345 #else
346 SInt32 value;
347 // if it's not a button and it's not a hatswitch then calibrate
348 if(( IOHIDElementGetType(pCurrentHIDElement) != kIOHIDElementTypeInput_Button ) &&
349 ( IOHIDElementGetUsagePage(pCurrentHIDElement) == 0x01 && IOHIDElementGetUsage(pCurrentHIDElement) != kHIDUsage_GD_Hatswitch))
351 value = IOHIDElement_GetValue(pCurrentHIDElement, kIOHIDValueScaleTypeCalibrated);
353 else
355 value = IOHIDElement_GetValue(pCurrentHIDElement, kIOHIDValueScaleTypePhysical);
357 #endif
358 SetInt(a, value);
360 else SetNil(a);
361 return errNone;
366 int prHIDSetValue(VMGlobals *g, int numArgsPushed);
367 int prHIDSetValue(VMGlobals *g, int numArgsPushed)
369 PyrSlot *a = g->sp - 3; //class
370 PyrSlot *b = g->sp - 2; //locID
371 PyrSlot *c = g->sp - 1; //element device
372 PyrSlot *d = g->sp; //value cookie
373 int locID, cookieNum, value;
374 int err = slotIntVal(b, &locID);
375 if (err) return err;
376 err = slotIntVal(c, &cookieNum);
377 if (err) return err;
378 IOHIDElementCookie cookie = (IOHIDElementCookie) cookieNum;
379 err = slotIntVal(d, &value);
380 if (err) return err;
381 //look for the right device:
382 IOHIDDeviceRef pCurrentHIDDevice = HIDGetFirstDevice ();
383 while (pCurrentHIDDevice && (IOHIDDevice_GetLocationID(pCurrentHIDDevice) !=locID))
384 pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);
385 if(!pCurrentHIDDevice) return errFailed;
386 //look for the right element:
387 IOHIDElementRef pCurrentHIDElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeAll);
388 // use gElementCookie to find current element
389 while (pCurrentHIDElement && (IOHIDElementGetCookie(pCurrentHIDElement) != cookie))
390 pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeAll);
391 //struct IOHIDEventStruct
393 // IOHIDElementType type;
394 // IOHIDElementCookie elementCookie;
395 // SInt32 value;
396 // AbsoluteTime timestamp;
397 // UInt32 longValueSize;
398 // void * longValue;
399 //};
401 if (pCurrentHIDElement)
403 #if(SC_MAC_HIDSTYLE_10_4)
404 IOHIDEventStruct event =
406 kIOHIDElementTypeOutput,
407 pCurrentHIDElement->cookie,
408 value,
409 {0},
410 sizeof(int),
411 NULL
413 SInt32 value = HIDSetElementValue (pCurrentHIDDevice, pCurrentHIDElement, &event);
414 // if it's not a button and it's not a hatswitch then calibrate
415 // if(( pCurrentHIDElement->type != kIOHIDElementTypeInput_Button ) &&
416 // ( pCurrentHIDElement->usagePage == 0x01 && pCurrentHIDElement->usage != kHIDUsage_GD_Hatswitch))
417 // value = HIDCalibrateValue ( value, pCurrentHIDElement );
418 #else
419 IOHIDValueRef valueref = IOHIDValueCreateWithIntegerValue(0, pCurrentHIDElement, 0, value);
420 IOHIDDeviceSetValue(pCurrentHIDDevice, pCurrentHIDElement, valueref);
421 CFRelease(valueref);
422 #endif
423 SetInt(a, value);
425 else SetNil(a);
426 return errNone;
430 void PushQueueEvents_RawValue ();
431 void PushQueueEvents_RawValue (){
433 #if(SC_MAC_HIDSTYLE_10_4)
434 IOHIDEventStruct event;
435 #else
436 IOHIDValueRef value_ref = 0;
437 #endif
438 IOHIDDeviceRef pCurrentHIDDevice = HIDGetFirstDevice ();
439 int numdevs = gNumberOfHIDDevices;
440 unsigned char result;
441 for(int i=0; i< numdevs; i++){
442 #if(SC_MAC_HIDSTYLE_10_4)
443 result = HIDGetEvent(pCurrentHIDDevice, (void*) &event);
444 #else
445 result = HIDGetEvent(pCurrentHIDDevice, &value_ref);
446 #endif
447 if(result && compiledOK) {
448 #if(SC_MAC_HIDSTYLE_10_4)
449 SInt32 value = event.value;
450 #else
451 SInt32 value = IOHIDValueGetIntegerValue(value_ref);
452 #endif
453 int vendorID = IOHIDDevice_GetVendorID(pCurrentHIDDevice);;
454 int productID = IOHIDDevice_GetProductID(pCurrentHIDDevice);
455 int locID = IOHIDDevice_GetLocationID(pCurrentHIDDevice);
456 #if(SC_MAC_HIDSTYLE_10_4)
457 IOHIDElementCookie cookie = (IOHIDElementCookie) event.elementCookie;
458 #else
459 IOHIDElementCookie cookie = IOHIDElementGetCookie(IOHIDValueGetElement(value_ref));
460 CFRelease(value_ref);
461 #endif
462 VMGlobals *g = gMainVMGlobals;
463 pthread_mutex_lock (&gLangMutex);
464 g->canCallOS = false; // cannot call the OS
465 ++g->sp; SetObject(g->sp, s_hid->u.classobj); // Set the class HIDService
466 //set arguments:
467 ++g->sp;SetInt(g->sp, vendorID);
468 ++g->sp;SetInt(g->sp, productID);
469 ++g->sp;SetInt(g->sp, locID);
470 ++g->sp;SetInt(g->sp, (int) cookie);
471 ++g->sp;SetInt(g->sp, value);
472 runInterpreter(g, s_hidAction, 6);
473 g->canCallOS = false; // cannot call the OS
474 pthread_mutex_unlock (&gLangMutex);
477 /* FIXME: this does not seem to be working
478 if ( !HIDIsValidDevice(pCurrentHIDDevice) )
479 { // readError
480 post("HID: read Error\n");
481 int locID = pCurrentHIDDevice->locID;
482 VMGlobals *g = gMainVMGlobals;
483 pthread_mutex_lock (&gLangMutex);
484 g->canCallOS = false; // cannot call the OS
485 ++g->sp; SetObject(g->sp, s_hid->u.classobj); // Set the class HIDService
486 ++g->sp;SetInt(g->sp, locID);
487 runInterpreter(g, s_readError, 2);
488 g->canCallOS = false; // cannot call the OS
489 pthread_mutex_unlock (&gLangMutex);
492 pCurrentHIDDevice = HIDGetNextDevice(pCurrentHIDDevice);
496 void PushQueueEvents_CalibratedValue ();
497 void PushQueueEvents_CalibratedValue (){
499 #if(SC_MAC_HIDSTYLE_10_4)
500 IOHIDEventStruct event;
501 #else
502 IOHIDValueRef value_ref = 0;
503 #endif
504 IOHIDDeviceRef pCurrentHIDDevice = HIDGetFirstDevice ();
506 int numdevs = gNumberOfHIDDevices;
507 unsigned char result;
508 for(int i=0; i< numdevs; i++){
510 #if(SC_MAC_HIDSTYLE_10_4)
511 result = HIDGetEvent(pCurrentHIDDevice, (void*) &event);
512 #else
513 result = HIDGetEvent(pCurrentHIDDevice, &value_ref);
514 #endif
515 if(result && compiledOK) {
516 #if(SC_MAC_HIDSTYLE_10_4)
517 SInt32 value = event.value;
518 #else
519 SInt32 value = IOHIDValueGetScaledValue(value_ref, kIOHIDValueScaleTypeCalibrated);
520 #endif
521 int vendorID = IOHIDDevice_GetVendorID(pCurrentHIDDevice);;
522 int productID = IOHIDDevice_GetProductID(pCurrentHIDDevice);
523 int locID = IOHIDDevice_GetLocationID(pCurrentHIDDevice);
524 #if(SC_MAC_HIDSTYLE_10_4)
525 IOHIDElementCookie cookie = (IOHIDElementCookie) event.elementCookie;
526 #else
527 IOHIDElementCookie cookie = IOHIDElementGetCookie(IOHIDValueGetElement(value_ref));
528 CFRelease(value_ref);
529 #endif
530 IOHIDElementRef pCurrentHIDElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeAll);
531 // use gElementCookie to find current element
532 while (pCurrentHIDElement && ( (IOHIDElementGetCookie(pCurrentHIDElement)) != cookie))
533 pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeAll);
535 if (pCurrentHIDElement)
537 #if(SC_MAC_HIDSTYLE_10_4)
538 value = HIDCalibrateValue(value, pCurrentHIDElement);
539 #endif
540 //find element to calibrate
541 VMGlobals *g = gMainVMGlobals;
542 pthread_mutex_lock (&gLangMutex);
543 g->canCallOS = false; // cannot call the OS
544 ++g->sp; SetObject(g->sp, s_hid->u.classobj); // Set the class HIDService
545 //set arguments:
546 ++g->sp;SetInt(g->sp, vendorID);
547 ++g->sp;SetInt(g->sp, productID);
548 ++g->sp;SetInt(g->sp, locID);
549 ++g->sp;SetInt(g->sp, (int) cookie);
550 ++g->sp;SetInt(g->sp, value);
551 runInterpreter(g, s_hidAction, 6);
552 g->canCallOS = false; // cannot call the OS
553 pthread_mutex_unlock (&gLangMutex);
556 /* FIXME: this does not seem to be working!
557 if ( !HIDIsValidDevice(pCurrentHIDDevice) )
558 { // readError
559 post("HID: read Error\n");
560 int locID = pCurrentHIDDevice->locID;
561 VMGlobals *g = gMainVMGlobals;
562 pthread_mutex_lock (&gLangMutex);
563 g->canCallOS = false; // cannot call the OS
564 ++g->sp; SetObject(g->sp, s_hid->u.classobj); // Set the class HIDService
565 ++g->sp;SetInt(g->sp, locID);
566 runInterpreter(g, s_readError, 2);
567 g->canCallOS = false; // cannot call the OS
568 pthread_mutex_unlock (&gLangMutex);
570 pCurrentHIDDevice = HIDGetNextDevice(pCurrentHIDDevice);
574 static pascal void IdleTimer (EventLoopTimerRef inTimer, void* userData);
575 static pascal void IdleTimer (EventLoopTimerRef inTimer, void* userData)
577 #pragma unused (inTimer, userData)
578 PushQueueEvents_CalibratedValue ();
580 int prHIDReleaseDeviceList(VMGlobals *g, int numArgsPushed);
581 int prHIDReleaseDeviceList(VMGlobals *g, int numArgsPushed)
583 releaseHIDDevices();
584 return errNone;
586 static EventLoopTimerUPP GetTimerUPP (void);
587 static EventLoopTimerUPP GetTimerUPP (void)
589 static EventLoopTimerUPP sTimerUPP = NULL;
591 if (sTimerUPP == NULL)
592 sTimerUPP = NewEventLoopTimerUPP (IdleTimer);
594 return sTimerUPP;
597 typedef void (*IOHIDCallbackFunction)
598 (void * target, IOReturn result, void * refcon, void * sender);
602 void callback (void * target, IOReturn result, void * refcon, void * sender);
603 void callback (void * target, IOReturn result, void * refcon, void * sender)
607 int prHIDRunEventLoop(VMGlobals *g, int numArgsPushed);
608 int prHIDRunEventLoop(VMGlobals *g, int numArgsPushed)
610 PyrSlot *a = g->sp - 1; //class
611 PyrSlot *b = g->sp; //num
612 double eventtime;
613 int err = slotDoubleVal(b, &eventtime);
614 if (err) return err;
615 if(gTimer)
617 RemoveEventLoopTimer(gTimer);
618 gTimer = NULL;
620 InstallEventLoopTimer (GetCurrentEventLoop(), 0, (EventTimerInterval) eventtime, GetTimerUPP (), 0, &gTimer);
621 //HIDSetQueueCallback(pCurrentHIDDevice, callback);
622 return errNone;
625 int prHIDQueueDevice(VMGlobals *g, int numArgsPushed);
626 int prHIDQueueDevice(VMGlobals *g, int numArgsPushed)
629 PyrSlot *a = g->sp - 1; //class
630 PyrSlot *b = g->sp; //locID device
631 int locID;
632 int err = slotIntVal(b, &locID);
633 if (err) return err;
634 //look for the right device:
635 IOHIDDeviceRef pCurrentHIDDevice = HIDGetFirstDevice ();
636 while (pCurrentHIDDevice && (IOHIDDevice_GetLocationID(pCurrentHIDDevice) !=locID))
637 pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);
638 if(!pCurrentHIDDevice) return errFailed;
639 HIDQueueDevice(pCurrentHIDDevice);
640 return errNone;
643 int prHIDQueueElement(VMGlobals *g, int numArgsPushed);
644 int prHIDQueueElement(VMGlobals *g, int numArgsPushed)
647 PyrSlot *a = g->sp - 2; //class
648 PyrSlot *b = g->sp - 1; //locID device
649 PyrSlot *c = g->sp; //element cookie
650 int locID, cookieNum;
651 int err = slotIntVal(b, &locID);
652 if (err) return err;
653 err = slotIntVal(c, &cookieNum);
654 if (err) return err;
655 IOHIDElementCookie cookie = (IOHIDElementCookie) cookieNum;
656 //look for the right device:
657 IOHIDDeviceRef pCurrentHIDDevice = HIDGetFirstDevice ();
658 while (pCurrentHIDDevice && (IOHIDDevice_GetLocationID(pCurrentHIDDevice) !=locID))
659 pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);
660 if(!pCurrentHIDDevice) return errFailed;
661 //look for the right element:
662 IOHIDElementRef pCurrentHIDElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeAll);
663 // use gElementCookie to find current element
664 while (pCurrentHIDElement && (IOHIDElementGetCookie(pCurrentHIDElement) != cookie))
665 pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeAll);
666 if(!pCurrentHIDElement) return errFailed;
667 HIDQueueElement(pCurrentHIDDevice, pCurrentHIDElement);
668 return errNone;
671 int prHIDDequeueElement(VMGlobals *g, int numArgsPushed);
672 int prHIDDequeueElement(VMGlobals *g, int numArgsPushed)
675 PyrSlot *a = g->sp - 2; //class
676 PyrSlot *b = g->sp - 1; //locID device
677 PyrSlot *c = g->sp; //element cookie
678 int locID, cookieNum;
679 int err = slotIntVal(b, &locID);
680 if (err) return err;
681 err = slotIntVal(c, &cookieNum);
682 if (err) return err;
683 IOHIDElementCookie cookie = (IOHIDElementCookie) cookieNum;
684 //look for the right device:
685 IOHIDDeviceRef pCurrentHIDDevice = HIDGetFirstDevice ();
686 while (pCurrentHIDDevice && (IOHIDDevice_GetLocationID(pCurrentHIDDevice) !=locID))
687 pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);
688 if(!pCurrentHIDDevice) return errFailed;
689 //look for the right element:
690 IOHIDElementRef pCurrentHIDElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeAll);
691 while (pCurrentHIDElement && (IOHIDElementGetCookie(pCurrentHIDElement) != cookie))
692 pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeAll);
693 if(!pCurrentHIDElement) return errFailed;
694 HIDDequeueElement(pCurrentHIDDevice, pCurrentHIDElement);
695 return errNone;
698 int prHIDDequeueDevice(VMGlobals *g, int numArgsPushed);
699 int prHIDDequeueDevice(VMGlobals *g, int numArgsPushed)
702 PyrSlot *a = g->sp - 1; //class
703 PyrSlot *b = g->sp; //locID device
704 int locID;
705 int err = slotIntVal(b, &locID);
706 if (err) return err;
707 //look for the right device:
708 IOHIDDeviceRef pCurrentHIDDevice = HIDGetFirstDevice ();
709 while (pCurrentHIDDevice && (IOHIDDevice_GetLocationID(pCurrentHIDDevice) !=locID))
710 pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);
711 if(!pCurrentHIDDevice) return errFailed;
712 HIDDequeueDevice(pCurrentHIDDevice);
713 return errNone;
716 int prHIDStopEventLoop(VMGlobals *g, int numArgsPushed);
717 int prHIDStopEventLoop(VMGlobals *g, int numArgsPushed)
719 if (gTimer)
721 RemoveEventLoopTimer(gTimer);
722 gTimer = NULL;
724 return errNone;
728 void initHIDPrimitives()
730 int base, index;
732 releaseHIDDevices();
734 s_hid = getsym("HIDDeviceService");
735 s_hidAction = getsym("prHidAction");
736 s_readError = getsym("prReadError");
738 base = nextPrimitiveIndex();
739 index = 0;
740 definePrimitive(base, index++, "_HIDBuildDeviceList", prHIDBuildDeviceList, 3, 0);
742 definePrimitive(base, index++, "_HIDGetElementListSize", prHIDGetElementListSize, 2, 0);
743 definePrimitive(base, index++, "_HIDBuildElementList", prHIDBuildElementList, 3, 0);
745 definePrimitive(base, index++, "_HIDGetValue", prHIDGetValue, 3, 0);
746 definePrimitive(base, index++, "_HIDSetValue", prHIDSetValue, 4, 0);
748 definePrimitive(base, index++, "_HIDReleaseDeviceList", prHIDReleaseDeviceList, 1, 0);
749 definePrimitive(base, index++, "_HIDRunEventLoop", prHIDRunEventLoop, 2, 0);
750 definePrimitive(base, index++, "_HIDStopEventLoop", prHIDStopEventLoop, 1, 0);
751 definePrimitive(base, index++, "_HIDQueueDevice", prHIDQueueDevice, 2, 0);
752 definePrimitive(base, index++, "_HIDDequeueDevice", prHIDDequeueDevice, 2, 0);
753 definePrimitive(base, index++, "_HIDDequeueElement", prHIDDequeueElement, 3, 0);
754 definePrimitive(base, index++, "_HIDQueueElement", prHIDQueueElement, 3, 0);
757 #else // !SC_DARWIN
758 void initHIDPrimitives()
760 //other platforms?
762 #endif // SC_DARWIN