From 9f81d2eb96da71f0c1fc1476bc35ce78def3038b Mon Sep 17 00:00:00 2001 From: maride Date: Sat, 2 Apr 2016 15:32:35 +0200 Subject: [PATCH] Add HID Utilities and ForceFeedback Patch functions with same signature --- .../ForceFeedback.framework/ForceFeedback | Bin 0 -> 19208 bytes .../Headers/ForceFeedback.h | 816 ++++++ .../Headers/ForceFeedbackConstants.h | 572 +++++ .../Headers/IOForceFeedbackLib.h | 447 ++++ .../Resources/Info.plist | 26 + .../Resources/version.plist | 18 + .../Versions/A/ForceFeedback | Bin 0 -> 19208 bytes .../Versions/A/Headers/ForceFeedback.h | 816 ++++++ .../A/Headers/ForceFeedbackConstants.h | 572 +++++ .../Versions/A/Headers/IOForceFeedbackLib.h | 447 ++++ .../Versions/A/Resources/Info.plist | 26 + .../Versions/A/Resources/version.plist | 18 + .../Versions/Current/ForceFeedback | Bin 0 -> 19208 bytes .../Versions/Current/Headers/ForceFeedback.h | 816 ++++++ .../Current/Headers/ForceFeedbackConstants.h | 572 +++++ .../Current/Headers/IOForceFeedbackLib.h | 447 ++++ .../Versions/Current/Resources/Info.plist | 26 + .../Versions/Current/Resources/version.plist | 18 + HID Utilities/HID_Utilities_External.h | 476 ++++ HID_Config_Utilities.c | 425 ++++ HID_Error_Handler.c | 104 + HID_Error_Handler.h | 74 + HID_Name_Lookup.c | 347 +++ HID_Name_Lookup.h | 87 + HID_Queue_Utilities.c | 632 +++++ HID_Queue_Utilities.h | 114 + HID_Transaction_Utilities.c | 316 +++ HID_Utilities.c | 2197 +++++++++++++++++ HID_Utilities.h | 256 ++ HID_Utilities_External.h | 476 ++++ HID_Utilities_Internal.h | 54 + ImmrHIDUtilAddOn.c | 95 + ImmrHIDUtilAddOn.h | 11 + game.xcodeproj/project.pbxproj | 46 + 34 files changed, 11347 insertions(+) create mode 100755 Frameworks/ForceFeedback.framework/ForceFeedback create mode 100755 Frameworks/ForceFeedback.framework/Headers/ForceFeedback.h create mode 100755 Frameworks/ForceFeedback.framework/Headers/ForceFeedbackConstants.h create mode 100755 Frameworks/ForceFeedback.framework/Headers/IOForceFeedbackLib.h create mode 100755 Frameworks/ForceFeedback.framework/Resources/Info.plist create mode 100755 Frameworks/ForceFeedback.framework/Resources/version.plist create mode 100755 Frameworks/ForceFeedback.framework/Versions/A/ForceFeedback create mode 100755 Frameworks/ForceFeedback.framework/Versions/A/Headers/ForceFeedback.h create mode 100755 Frameworks/ForceFeedback.framework/Versions/A/Headers/ForceFeedbackConstants.h create mode 100755 Frameworks/ForceFeedback.framework/Versions/A/Headers/IOForceFeedbackLib.h create mode 100755 Frameworks/ForceFeedback.framework/Versions/A/Resources/Info.plist create mode 100755 Frameworks/ForceFeedback.framework/Versions/A/Resources/version.plist create mode 100755 Frameworks/ForceFeedback.framework/Versions/Current/ForceFeedback create mode 100755 Frameworks/ForceFeedback.framework/Versions/Current/Headers/ForceFeedback.h create mode 100755 Frameworks/ForceFeedback.framework/Versions/Current/Headers/ForceFeedbackConstants.h create mode 100755 Frameworks/ForceFeedback.framework/Versions/Current/Headers/IOForceFeedbackLib.h create mode 100755 Frameworks/ForceFeedback.framework/Versions/Current/Resources/Info.plist create mode 100755 Frameworks/ForceFeedback.framework/Versions/Current/Resources/version.plist create mode 100755 HID Utilities/HID_Utilities_External.h create mode 100755 HID_Config_Utilities.c create mode 100755 HID_Error_Handler.c create mode 100755 HID_Error_Handler.h create mode 100755 HID_Name_Lookup.c create mode 100755 HID_Name_Lookup.h create mode 100755 HID_Queue_Utilities.c create mode 100755 HID_Queue_Utilities.h create mode 100755 HID_Transaction_Utilities.c create mode 100755 HID_Utilities.c create mode 100755 HID_Utilities.h create mode 100755 HID_Utilities_External.h create mode 100755 HID_Utilities_Internal.h create mode 100755 ImmrHIDUtilAddOn.c create mode 100755 ImmrHIDUtilAddOn.h diff --git a/Frameworks/ForceFeedback.framework/ForceFeedback b/Frameworks/ForceFeedback.framework/ForceFeedback new file mode 100755 index 0000000000000000000000000000000000000000..b1c427c4cf97cbb0bdb0118121c3365924fe79d3 GIT binary patch literal 19208 zcmeHP4{)2sm4Eu=1`2iA)^gG-_g6(~)C2NZ4`ZivbrqJu?lJ6QOYRQv z{od|=(r3js;ih*pH)9RUzTJJ_dvD*qef#!(&iBc0|MMS-=q42Y%|p4K$a)_24^T|_ z&l(7{Z|Z1AOa1olW1w2KL|u$V5sHO71A$~Xm1Ic%u719FoM=^)h-)(Icp6!C5H#YE z(7;gNwpcVUkR050HI2_Z@aS$Lu8lOvrifGq0-=FqBGUh$>bRQ5`WG;?l}OY%IgIoG zvkoQ#fkt1uPZ2_OSm?kGi098Wu?~3ttV77(6-)*hlE3MnrxK+{18=a)J<~N5?b2IJ z^C}teJkPh9YXc4AGtpo`=`o&6Oh=;(*nZI9+Cam^^AUCt2=rqSu@a>Cr!7dVgf$qWn&~$R}Os$ZEYXc3_b^JX4u%6w<1)WA8JwU@^RC8^hAOE zeM@9pBA6Ij-;@aUg&&P2dI#1w#S)=#Q#jnUEg0%u*R2n%|7tif5Q+564VgL}s5$^SzrR$?3_9 zA)RK8r1?aG>H#s$!GXm3Xk;4~sj78%t%F%dw(%okjmn|(all_9YI4E^E&zrPqE;0C zEmVc=^Hvnpja90C6Ezlh6R*p9qJ}K$+feUD4enl4bh9dU^t%Bwoy91u>$%^Y2L4}Z zAZ;@rzUz4^8s2R_oVHmG4{M=R{o{7ZJbtBp_%X}jbcsc8`|r`L&f)KdQky3y-^xAL zBcH49#WTHEoWl{zVaDU}(Q}g@Wldyzs$z1Cd5l~zANGvES%y~cc4x>7I>$1oUD!Fk zgH+}jv6B|M;$^;|QK6Zr$6Z04EZ0uZxE~!?CNDDG^s_5dOgDXe zZ7SWhH0ADOTDKia4=)`8{c7zwvZDPk(?;7i`Wz9{9Qod_Q%sj>9tADnRONV~UC66o z9^U#p?Ua6QWh%4gvWuMyWEq35#&*64y`3Pc(}+e6{W|5RRWGY~y`lwaOvrJNj(DE8 zlY7_Y8jMGjY)^6D=t*kScK!Q1?gQiiaUnNo`>FC*YK~hy&x7X} z%C6hS(f{(usSi_(2Y6WYpCA+KW#k3Xw<*0{=%y0#wgTtIYRly0h_=K&@}mz~-U|8b zswD<_ZRnp5{k%D{^L^Ia30-gcdK^DFd0MQ;Ua=mX=|`8QG%Hohb)IJh>=N+7qARSg zx)by+@H^ZZeSo?Va^4TUopPV0&RU{3YMu0xS})yLH%8xqPTbI^WAp%d>N?57da3i$ z=xC7qbxvv<^-)V5(XmmiC(m=#MD2cBxrpsSdsOJ^;dG~%vrD^~T%JyiIzwc^VPf%S zic*;`QMKNeS;P4B(hRZ%jk2*^EECJavalR1gXDkf(|P_Y|DgDHg1=4Y<)X<+-wx}Q z0-1`v8S8m%uR*3tqS`g9?N#&dar!dWH#3!F)oJMcezIJeLFR4OE_1~>gUt0Tv-hB> zYX-WZ&p`LFJl$JAP;^UXpxgBs=-zIi`-G%RugpL3dzcA3fL($zj1KsY=KsS@8 zTXBZzVox^~tp5$(jCsoXWA9KEt+x9z=C=Un?5Bzzf8I|f_TAI%qX(~Dt`)yB$hGNH z)~Dw)(A|@#>-_DftWV@K(5*Glefm?@=b>w-yWC*^PGSF8pBD<&XR$Y9YMgn0nyRMT zpT3OAj{e-*>HF4~p(|L^5`90*b*A&^vlsMDps%c;?=|?USJ;Od{AaImzHA#PjkEiz zWrp=%u}Pgrtp)RjT~f=Gc_aFEA!3J)Y9L!~Zo|&6?Hyio|GQ~;Qk>`IkTEwGz&7^L zI7^P;92xr|&JF#nJ$_*F9gasJuPvQgI)roG%jYhi7aPx-_>A4naRh2D{q)KdpRwC6 zYs|mIg+1auNcQ?pje@;o@soKRXUsN1QfdV)4+GGFG&@~|x6@fFPd9h~zi%-M^1TtMx{TsqLdhiReh z!MyBfw}S4oX#2(dh|Xh!gR6&(80Q*dq-(9>~XX1t4E5+Fr62d2dDkpqL9{AI!xJo5_wIrxG{(Dr)QY^G8$J z<%p4rFn`2LnF`vyXCv8$S8hg(N0fPt%Jg`b<1W~BCHU=jKSyPmm14ZgIL>jhjHj0T zV&wZAcaf80##*dF?V8_rX!Efa%gH|a_lQ@1F80Hl!=bO`VyhowFK}$dF*NT9j@k4W z^v*FT8|%VxFYkxYF&WQbP8WEuA%3=JuO~a;uFOX44e-KPIrL1~`DDXG>CVFO~D&2F@#j-gUo$%|i!kg+AVdjk-e&GQ8f(E~EK>39O(k~#slYSvHonI*5&$he${iE;;AHD$@ zOfu#-jX_US`~m28V2`|xy`J|8;K}@WuVR0DMh!lP`TD869yDk63801f{t0}-;-Bk2 zf#;I<35)mfoY)>=BX9k0`U9RX>&8!uoAdtQ=0AQme{k~wu?Fx5kk`R`w$QdPPHBsU z?dnbaZu3LflGuNy$+KxM-Io65(jon9s`J98e2BqeQ`m!J>C<0KjW&VCzLlx;Yim=& z&UTn;u!ep=E&7=8*k_<0e#hik=fK(y<1YFDS?kWg2h^keb*e^jqEw<(`JSY%kzMb@ zZ!EYw{S6T(wqsv7r7aQeV~a9qR~p(6qg`ca2hpxJw7(+nb&Hxuygy@q^pv)gO0vtS zWb`P?tI*Gr;+$~fj%;IJ2))=*TiHjluX5wQg1U_L1)Lfb7m5R=9Hj&_z1laiw=4gF zb=l)SMpo7}bSiQKBR~Ey1wZO=pS4ULg?)|uf!?)$me?2~eEF42|Ok(W}S&CJ@VFLZ^A4}jLS>DD>J(XaO3%@*r z|9eN^Lr=ih{h#hXPh-p~@3mAVebi0=pXD z*PFP{gNAPFub-T}B5ZtSJ$qmeC7dV1nt0hZP&YC!HGfxb{-BF3Fi9+=#i{W9&oi53`)Qo^rMlUOJ@n0gV={8PCVW`w@2L z$*eN$f5?PAP^Co>ue^cv_!j&U{1C61`w;dj{F1&Ga&ls?80dSo$Aq5YPs|p!1MqYq zmdg7W$)lWkC|k(wFQ$1sGdaO?H~6nkzQ;^I|Dsmd2j_VtKg`LuqsW84JU{L`SX9M( zuI>cZ5i;@q&eX&IAYL}eQK{P`a5?YhuH`!r(RbhrIREB>p6^H7;YJQl?Blc4iM9pt z$s1_9mUs!yF(D;4#n47EBRVjUX}x6qp0}~(N@5h@3_o+nSu9^fwvhsviF#; z;3;#Bg}E_71LwiJh`ro(oya`~k#qFojPoJq=tSfY_vE!&z#3@*K5pI6=p7 zZ^M0U;ekBw8$LGhMh@E2S-^X0{tWz>7xQ7AG9Tu_^qIDt+d`j#{(b{}!~+&8pg%Q_ zc1`pb$o$7JuiFjv2Kw-gW{zKtx|^C$yEginy!;E#80b4e-&;U`YF_Qy=vNr%4;$!v zktaJ_K!0j}?3(D8oHWp1W}vTuzE(hgYM$)c=m+!k7aYsehvAdSSwMekzU30^;pOUBI{g$);t8HKH?dyF8`ui1qTipp8 z37g@Sko!+0H-)TXsKH;aRJqqUIbvVf+CX~MR+E!Gxr8Dy%KG8KKmIXswj zhsxLG-XXJ%y&jzWjfnB`K4pyWCF!GU5$Bm+m2snKJoELO?G&?Z`F2=Nxr!{4kVC_r zLcb$Iw?&+9;k!dM`t`da_h(dp4f^#vBlkyCzZ?Df-I4n_m&|m$;=Y1+y_+XL`h&c0 znLkSRF2%Z7yg6S6KL*_LfllGe&T8-F_QNIU+Ntd80^6ppCu#rYkEYoFYUB$s*FTN@ zo1eML{-G=E0f$(}<*>nJ_6_h8h=;5}neVU;=WGnP(q7CR!WPB*dFvv~(TjbT&TIu8 zu@*Q#u&>zeaE}oC0yZ!K-!*l=U&s61T*B+J%C0(l#cO#Hqad&+XZK}NNwOf^iO>0Zm8f_`j!Hj*2%@>$@3{&K!j z$#NciofwyAg9G~$=fglJ&W3{&<^3pq&AERZ@j z?-T0}JnWw`F~{w>eH;~gSLoWjW}wrIy#`<4pc>F>bS;&+A0OV4@cO#{8EcQ+)yRXt zOo_W9@)J0Ji0_>6_vFUAf}_~u#`_}p$uj`YDW4$nU5qDuf}Xd^`-E}f6OgB1S=c9F zp2i%-7|SB>e#l*64S@H!rgBZd^>RKyj+-rzJuYO0Y%D9!LCDJY+x)$@g7-R}74sZG z%z}A#q{ryC_CqT^QFCp@^CIuY&yRfj{ge~u4WFT)pV4?eG%HlNoV7l3{X%c;*_`c!gXrL%*0N0Yyc=kst<54P-f=u4lA zF$aY>f#0GWR^eo4!HFxJ z_$)ZB3a51zoN9$rJqwOq;n-)!dHbTodHdolI1>tIViufng)=@2PFCS$XTgapocJs_ ztqP}g7MyB@Q#}igUE$bg#+kS%aV9R#f-|9TCKv~QOOC$-4}^lzDE}4pU^EI#iiZcT`Wxjsw-9PRJB9Z<*F{@8Z!O$LgYO0@9#?h zpI(TZDPa68zf=8oB5Uz-{Oe!j9WW>B3JDiq0Q?07p9TD93IwiB?X zVB|)uqY|E91^9@BuWJE(O2Uz;zOKqyPsc zyp-{GO86EB;DZt_e+BU0s{UsH|5CyZ{`bsRRR0OA-7TvB6kwNxmpK7@6r2RSMZzmF zUsF`Vt2+QIzH6g^pOpQsR={Hl9s@is;j#(9Ka#NhDZoElKqeFCf&l+cz{m;V)w@-~ zk*$CiNO;A2fXgNP1mrhY2^je#z<0|2L%RU)5-@U1fS;AHhv~c~ z;pR(#Cl-*|#Ca>gA4)ihd08L>_hVXQsRlmD+?3_M1!OUC-V6O5+|RiyzLm^x8dA8(_40DeJ~Zj^qM1WFQk`1kE}C(2Ji2jiADlv6O1NqjoP zh5jC*+gYePP`-dtgMxq4PM=3vhr&3YLs^4@f8$PgQ_Qb==vEYD>BWaAR-uN@X)Vg1 zgpLM6_RVKeH!%Xw zq3UI-UasmDs&=ZHzYhSqmSNP!AH0P46&pLJ!j^BN&Cj!}jL*7d{COz+V|n%e3lMz% zLIGUyx-brZ8-nX;@X<>a3)UH>2xT710xQ&MhAL6)C^w?qgi?x9hO!9dW|YM!@)}VY2Wi5&eRY?vPMJA{t(fUkyeFq2Y$6O%D$Sp_B&Q5EyI|-_`*ED7diQAP4i^Qi8h&lfi9K zL2=7{Ewb;=BgvkoNHi?J4$>M-_V7~}W`k(EFWfDfTbdgsdQ&3SmnXgj{lII$=Twrx z{vc{^iCA@5rrYg)i0Is??QqG2Ga9{xQ2q(h*ym`74Vf??hp~)AG#zMhl zEYTS54h}}Kw0(HR6T`=G`oevo_z;PgI=8Qj5g0s#Eq2#nB-#~D+#SRxXA<{r<1W@5 z5TcR(UT3%~0%H7BS0Ebv#*qHao^6r-E_?+k5N4SJ@mQokDUkwwJ@Um-peGyzVcE;y z=Ltk(vEISBM8-fMV0h&eXoyD#2e_bLa5FqYq3%BU#U`C?PdJLbC25OKITZ{99t^~# zX@Z__Fd1vdSArt_;)^z5(0nfzm=~27adQ~{pfMI6P>bacJ`(1B3cyq&_zF&#UwO5~ Z!=XrbBqTNw+d(YO3l>S_T-8-G|8HW8#+m>C literal 0 HcmV?d00001 diff --git a/Frameworks/ForceFeedback.framework/Headers/ForceFeedback.h b/Frameworks/ForceFeedback.framework/Headers/ForceFeedback.h new file mode 100755 index 0000000..59b8b5d --- /dev/null +++ b/Frameworks/ForceFeedback.framework/Headers/ForceFeedback.h @@ -0,0 +1,816 @@ +//----------------------------------------------------------------------------- +// File: ForceFeedback.h +// Contains: Public interfaces for ForceFeedback technology. +// Copyright: © 2002 by Apple Computer, Inc. All rights reserved. +// +//----------------------------------------------------------------------------- + +#ifndef _FORCEFEEDBACK_H_ +#define _FORCEFEEDBACK_H_ + +#if PRAGMA_ONCE +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! @header ForceFeedback.h + @abstract Public Interfaces to the Force Feedback implementation in Mac OS X. + @discussion The Force Feedback API allows developers to control Force Feedback devices attached to the system. It is a distilled version of the Force Feedback functionality found in Microsoft's DirectInput API. Developers familiar with that API should find this API to be similar. + +*/ + +#include +#if COREFOUNDATION_CFPLUGINCOM_SEPARATE +#include +#endif + +#include +#include +#include + +//----------------------------------------------------------------------------- +// The Version of the FF API +//----------------------------------------------------------------------------- + +enum { + kFFAPIMajorRev = 1, + kFFAPIMinorAndBugRev = 0, + kFFAPIStage = finalStage, + kFFAPINonRelRev = 0 +}; + +//----------------------------------------------------------------------------- +// Effect definition structures +//----------------------------------------------------------------------------- + +struct FFCONSTANTFORCE +{ + LONG lMagnitude; +}; +typedef struct FFCONSTANTFORCE FFCONSTANTFORCE; +typedef FFCONSTANTFORCE * PFFCONSTANTFORCE; + +struct FFRAMPFORCE +{ + LONG lStart; + LONG lEnd; + +}; +typedef struct FFRAMPFORCE FFRAMPFORCE; +typedef FFRAMPFORCE * PFFRAMPFORCE; + +struct FFPERIODIC +{ + DWORD dwMagnitude; + LONG lOffset; + DWORD dwPhase; + DWORD dwPeriod; + +}; +typedef struct FFPERIODIC FFPERIODIC; +typedef FFPERIODIC * PFFPERIODIC; + +struct FFCONDITION +{ + LONG lOffset; + LONG lPositiveCoefficient; + LONG lNegativeCoefficient; + DWORD dwPositiveSaturation; + DWORD dwNegativeSaturation; + LONG lDeadBand; + +}; +typedef struct FFCONDITION FFCONDITION; +typedef FFCONDITION * PFFCONDITION; + +struct FFCUSTOMFORCE +{ + DWORD cChannels; + DWORD dwSamplePeriod; + DWORD cSamples; + LPLONG rglForceData; + +}; +typedef struct FFCUSTOMFORCE FFCUSTOMFORCE; +typedef FFCUSTOMFORCE * PFFCUSTOMFORCE; + +struct FFENVELOPE +{ + DWORD dwSize; /* sizeof(FFENVELOPE) */ + DWORD dwAttackLevel; + DWORD dwAttackTime; /* Microseconds */ + DWORD dwFadeLevel; + DWORD dwFadeTime; /* Microseconds */ + +}; +typedef struct FFENVELOPE FFENVELOPE; +typedef FFENVELOPE * PFFENVELOPE; + +// IMPORTANT NOTE: OBJECT IDS cannot be used to identify trigger buttons +// in FFEFFECT.dwTriggerButton, and output axes in FFEFFECT.rgdwAxes[n]. +// Please use object offsets (FFJOFS_* constants), the only supported method. +struct FFEFFECT +{ + DWORD dwSize; /* sizeof(FFEFFECT) */ + DWORD dwFlags; /* FFEFF_* */ + DWORD dwDuration; /* Microseconds */ + DWORD dwSamplePeriod; /* Microseconds */ + DWORD dwGain; + DWORD dwTriggerButton; /* or FFEB_NOTRIGGER */ + DWORD dwTriggerRepeatInterval; /* Microseconds */ + DWORD cAxes; /* Number of axes */ + LPDWORD rgdwAxes; /* Array of axes */ + LPLONG rglDirection; /* Array of directions */ + PFFENVELOPE lpEnvelope; /* Optional */ + DWORD cbTypeSpecificParams; /* Size of params */ + void* lpvTypeSpecificParams; /* Pointer to params */ + DWORD dwStartDelay; /* Microseconds */ + +}; +typedef struct FFEFFECT FFEFFECT; +typedef FFEFFECT * PFFEFFECT; + +struct FFEFFESCAPE +{ + DWORD dwSize; + DWORD dwCommand; + void* lpvInBuffer; + DWORD cbInBuffer; + void* lpvOutBuffer; + DWORD cbOutBuffer; + +}; +typedef struct FFEFFESCAPE FFEFFESCAPE; +typedef FFEFFESCAPE * PFFEFFESCAPE; + +// NOTE: this structure has no DirectInput equivalent +struct FFCAPABILITIES +{ + NumVersion ffSpecVer; // Version of specification supported by the driver + UInt32 supportedEffects; // FFCAP_ET_*; including emulated effects + UInt32 emulatedEffects; // FFCAP_ET_*; driver-emulated effects + UInt32 subType; // FFCAP_TYPE_* + UInt32 numFfAxes; + UInt8 ffAxes[32]; + UInt32 storageCapacity; // number of effects that can be stored + // by the driver/device + UInt32 playbackCapacity; // number of effects that can be _simultaneously_ + // played back by the driver/device + NumVersion firmwareVer; // device firmware version, vendor-defined + NumVersion hardwareVer; // hardware version, vendor-defined + NumVersion driverVer; // driver version, vendor-defined + +}; +typedef struct FFCAPABILITIES FFCAPABILITIES; +typedef FFCAPABILITIES * PFFCAPABILITIES; + + + +//----------------------------------------------------------------------------- +// Object reference pointers +//----------------------------------------------------------------------------- + +// FFDeviceObjectReference and FFEffectObjectReference are opaque handles +// to objects created and maintained by the FF API. +// A FFDeviceObjectReference is obtained through a call to FFCreateDevice and +// refers to a specific attached device supporting force feedback. This +// reference may be passed to any of the "FFDevice" functions (below). When +// you are through with it, call FFReleaseDevice to release the memory. +// Similarly, a FFEffectObjectReference is obtained through a call to +// FFDeviceCreateEffect and refers to a created force feedback effect on a +// particular device. This reference may be passed to any of the "FFEffect" +// functions. Call FFDeviceReleaseEffect to unload the effect and clean up +// its memory. - Jeff Mallett 9/25/02 +// +typedef struct {} __FFDHIDDEN, * FFDeviceObjectReference; +typedef struct {} __FFEHIDDEN, * FFEffectObjectReference; + + +//----------------------------------------------------------------------------- +// FF (general) function prototypes +//----------------------------------------------------------------------------- + +/*! @function FFCreateDevice + @abstract Creates a new API device object from an OS object in preparation to use the device for force feedback. + @param hidDevice Pointer to a HID device object. + @param pdeviceReference Address of a variable to receive an opaque reference handle to a new device object. This reference can be used in subsequent calls to FFDevice* functions + @result If the method succeeds, and the device supports FF, the return value is FF_OK. +If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOINTERFACE +
FFERR_OUTOFMEMORY +
FFERR_INTERNAL +
+ @discussion When you are finished with the device, FFReleaseDevice must be called on the reference received in this function to dispose of the API device object. +*/ + +extern HRESULT +FFCreateDevice( + io_service_t hidDevice, + FFDeviceObjectReference * pDeviceReference + ); + + +/*! @function FFReleaseDevice + @abstract Disposes of an API device object created with FFCreateDevice. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @result If the method succeeds, and the device supports FF, the return value is FF_OK. +If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOINTERFACE +
FFERR_OUTOFMEMORY +
+ @discussion +*/ + +extern HRESULT +FFReleaseDevice( + FFDeviceObjectReference deviceReference + ); + + +/*! @function FFIsForceFeedback + @abstract Used to determine if a particular device provided by HID Manager is a force feedback device. + @param hidDevice Pointer to a HID device object to be tested for force feedback support. + @result If the method succeeds, and the device supports FF, the return value is FF_OK. If the method succeeds, and the device does not support FF, the return value is FFERR_NOINTERFACE. If the method fails, the return value is FFERR_INVALIDPARAM + @discussion When you are finished with the device, FFReleaseDevice must be called on the reference received in this function to dispose of the API device object. +*/ + +extern HRESULT +FFIsForceFeedback( + io_service_t hidDevice + ); + + +//----------------------------------------------------------------------------- +// FFDevice (device related) function prototypes +//----------------------------------------------------------------------------- + +/*! @function FFDeviceCreateEffect + @abstract Creates and initializes an instance of an effect identified by the effect UUID on the device. + @param deviceReference An opaque reference handle to a device object. This is obtained from a previous call to FFCreateDevice. + @param uuidRef Reference to the UUID identifying the effect to be created. Only predefined effect UUIDs are accepted. The following standard effect UUIDs are defined: +
+
kFFEffectType_ConstantForce_ID +
kFFEffectType_RampForce_ID +
kFFEffectType_Square_ID +
kFFEffectType_Sine_ID +
kFFEffectType_Triangle_ID +
kFFEffectType_SawtoothUp_ID +
kFFEffectType_SawtoothDown_ID +
kFFEffectType_Spring_ID +
kFFEffectType_Damper_ID +
kFFEffectType_Inertia_ID +
kFFEffectType_Friction_ID +
kFFEffectType_CustomForce_ID +
+
+ @param pEffectDefinition Pointer to FFEFFECT structure that provides parameters for the created effect. This parameter is optional. If it is NULL, the effect object is created without parameters. The application must then call the FFEffectSetParameters function to set the parameters of the effect before it can download the effect. + @param pEffectReference Address of a variable to receive an opaque reference handle to a new effect object. This reference can be used in subsequent calls to FFEffect* functions. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_UNSUPPORTEDAXIS +
FFERR_OUTOFMEMORY +
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_INVALIDDOWNLOADID +
FFERR_INTERNAL +
FFERR_EFFECTTYPEMISMATCH +
+ @discussion When you are finished with the effect, FFReleaseEffect must be called on the reference received in this function to dispose of the API effect object. +*/ + +extern HRESULT +FFDeviceCreateEffect( + FFDeviceObjectReference deviceReference, + CFUUIDRef uuidRef, + FFEFFECT * pEffectDefinition, + FFEffectObjectReference * pEffectReference + ); + + +/*! @function FFDeviceReleaseEffect + @abstract Disposes of an API effect object created with FFDeviceCreateEffect. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @param effectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
FFERR_GENERIC +
FFERR_INTERNAL +
FFERR_INVALIDDOWNLOADID +
+ @discussion +*/ + +extern HRESULT +FFDeviceReleaseEffect( + FFDeviceObjectReference deviceReference, + FFEffectObjectReference effectReference + ); + +/*! @function FFDeviceEscape + @abstract Sends a hardware-specific command to the device. + @param deviceReference An opaque reference handle to a device object. This is obtained from a previous call to FFCreateDevice. + @param pFFEffectEscape Pointer to FFEFFESCAPE structure that describes the command to be sent. On success, the cbOutBuffer member contains the number of bytes of the output buffer used. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_UNSUPPORTED +
+ @discussion Because each driver implements different escapes, it is the application's responsibility to ensure that it is sending the escape to the correct driver. +*/ +extern HRESULT +FFDeviceEscape( + FFDeviceObjectReference deviceReference, + FFEFFESCAPE * pFFEffectEscape + ); + +/*! @function FFDeviceGetForceFeedbackState + @abstract Retrieves the state of the device's force feedback system. + @param deviceReference An opaque reference handle to a device object. This is obtained from a previous call to FFCreateDevice. + @param pFFState Location for flags that describe the current state of the device's force feedback system. +The value is a combination of the following constants: +
+
FFGFFS_ACTUATORSOFF +
The device's force feedback actuators are disabled. +
+
FFGFFS_ACTUATORSON +
The device's force feedback actuators are enabled. +
+
FFGFFS_DEVICELOST +
The device suffered an unexpected failure and is in an indeterminate state. It must be reset either by unacquiring and reacquiring the device, or by sending a FFSFFC_RESET command. +
+
FFGFFS_EMPTY +
The device has no downloaded effects. +
+
FFGFFS_PAUSED +
Playback of all active effects has been paused. +
+
FFGFFS_POWEROFF +
The force feedback system is not currently available. If the device cannot report the power state, neither FFGFFS_POWERON nor FFGFFS_POWEROFF is returned. +
+
FFGFFS_POWERON +
Power to the force feedback system is currently available. If the device cannot report the power state, neither FFGFFS_POWERON nor FFGFFS_POWEROFF is returned. +
+
FFGFFS_SAFETYSWITCHOFF +
The safety switch is currently off; that is, the device cannot operate. If the device cannot report the state of the safety switch, neither FFGFFS_SAFETYSWITCHON nor FFGFFS_SAFETYSWITCHOFF is returned. +
+
FFGFFS_SAFETYSWITCHON +
The safety switch is currently on; that is, the device can operate. If the device cannot report the state of the safety switch, neither FFGFFS_SAFETYSWITCHON nor FFGFFS_SAFETYSWITCHOFF is returned. +
+
FFGFFS_STOPPED +
No effects are playing, and the device is not paused. +
+
FFGFFS_USERFFSWITCHOFF +
The user force feedback switch is currently off; that is, the device cannot operate. If the device cannot report the state of the user force feedback switch, neither FFGFFS_USERFFSWITCHON nor FFGFFS_USERFFSWITCHOFF is returned. +
+
FFGFFS_USERFFSWITCHON +
The user force feedback switch is currently on; that is, the device can operate. If the device cannot report the state of the user force feedback switch, neither FFGFFS_USERFFSWITCHON nor FFGFFS_USERFFSWITCHOFF is returned. +
+
Future versions can define additional flags. Applications should ignore any flags that are not currently defined. +
+ @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
+ @discussion +*/ + +extern HRESULT +FFDeviceGetForceFeedbackState( + FFDeviceObjectReference deviceReference, + FFState * pFFState + ); + +/*! @function FFDeviceSendForceFeedbackCommand + @abstract Sends a command to the device's force feedback system. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @param flags Single value indicating the desired change in state. The value can be one of the following: +
+
FFSFFC_CONTINUE +
Paused playback of all active effects is to be continued. It is an error to send this command when the device is not in a paused state. +
+
FFSFFC_PAUSE +
Playback of all active effects is to be paused. This command also stops the clock-on effects so that they continue playing to their full duration when restarted. +
+
While the device is paused, new effects cannot be started, and existing ones cannot be modified. Doing so can cause the subsequent FFSFFC_CONTINUE command to fail to perform properly. +
+
To abandon a pause and stop all effects, use the FFSFFC_STOPALL or FFSFCC_RESET commands. +
+
FFSFFC_RESET +
The device's force feedback system is to be put in its startup state. All effects are removed from the device, are no longer valid, and must be recreated if they are to be used again. The device's actuators are disabled. +
+
FFSFFC_SETACTUATORSOFF +
The device's force feedback actuators are to be disabled. While the actuators are off, effects continue to play but are ignored by the device. Using the analogy of a sound playback device, they are muted, rather than paused. +
+
FFSFFC_SETACTUATORSON +
The device's force feedback actuators are to be enabled. +
+
FFSFFC_STOPALL +
Playback of any active effects is to be stopped. All active effects are reset, but are still being maintained by the device and are still valid. If the device is in a paused state, that state is lost. +
+
This command is equivalent to calling the FFEffect_Stop method for each effect playing. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_INTERNAL +
+ @discussion +*/ + +extern HRESULT +FFDeviceSendForceFeedbackCommand( + FFDeviceObjectReference deviceReference, + FFCommandFlag flags + ); + +/*! @function FFDeviceSetForceFeedbackProperty + @abstract Retrieves the device's force feedback capabilities. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @param property The following property values are defined for a FF device: +
+
FFPROP_AUTOCENTER +
Specifies whether the actuated FF axes are self-centering. This property controls the device's "default centering spring". +
The pValue member points to a UInt32 can be one of the following values. +
0 - OFF: The device should not automatically center when the user releases the device. An application that uses force feedback should disable autocentering before playing effects. +
1 - ON: The device should automatically center when the user releases the device. +
Not all devices support the autocenter property. +
+
FFPROP_FFGAIN +
Sets the gain for the device. +
The pValue member points to a UInt32 that contains a gain value that is applied to all effects created on the device. The value is an integer in the range from 0 through 10,000, specifying the amount by which effect magnitudes should be scaled for the device. For example, a value of 10,000 indicates that all effect magnitudes are to be taken at face value. A value of 9,000 indicates that all effect magnitudes are to be reduced to 90% of their nominal magnitudes. +
Setting a gain value is useful when an application wants to scale down the strength of all force feedback effects uniformly, based on user preferences. + @param pValue Address of the location where the property value is to be read. SetForceFeedbackProperty will assume that the data is valid, and of the correct type. + @result If the method succeeds, the return value is FF_OK or FFERR_UNSUPPORTED. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
+ @discussion +*/ + +extern HRESULT +FFDeviceSetForceFeedbackProperty( + FFDeviceObjectReference deviceReference, + FFProperty property, + void * pValue + ); + +/*! @function FFDeviceGetForceFeedbackProperty + @abstract Gets properties that define the device behavior. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @param property The following property values are defined for a FF device (see FFDeviceSetForceFeedbackProperty for details): +
+
FFPROP_AUTOCENTER +
FFPROP_FFGAIN +
+ @param pValue Address of the location where the value associated with the property is to be stored. GetForceFeedbackProperty assumes that the pointer is valid, although it will perform a size check before writing the data to pValue + @param valueSize Size, in bytes, of data area pointed to by pValue. Size is compared to expected property size, and the function fails if a mismatch occurs. + @result If the method succeeds, the return value is FF_OK or FFERR_UNSUPPORTED. +If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
+ @discussion +*/ +extern HRESULT +FFDeviceGetForceFeedbackProperty( + FFDeviceObjectReference deviceReference, + FFProperty property, + void * pValue, + IOByteCount valueSize + ); + +/*! @function FFDeviceSetCooperativeLevel + @abstract Function is unimplemented in version 1.0 of this API + @discussion +*/ +extern HRESULT +FFDeviceSetCooperativeLevel( + FFDeviceObjectReference deviceReference, + void * taskIdentifier, + FFCooperativeLevelFlag flags + ); + +/*! @function FFDeviceGetForceFeedbackCapabilities + @abstract Retrieves the device's force feedback capabilities. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @param pFFCapabilities Pointer to a FFCAPABILITIES structure that is to be filled in by the this call. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
+ @discussion +*/ + +extern HRESULT +FFDeviceGetForceFeedbackCapabilities( + FFDeviceObjectReference deviceReference, + FFCAPABILITIES * pFFCapabilities + ); + + +//----------------------------------------------------------------------------- +// FFEffect (effect related) function prototypes +//----------------------------------------------------------------------------- + +/*! @function FFEffectDownload + @abstract Places the effect on the device. If the effect is already on the device, the existing effect is updated to match the values set by the FFEffectSetParameters method. + @param efffectRef An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @result If the method succeeds, the return value is FF_OK or S_FALSE. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_INVALIDDOWNLOADID +
FFERR_INTERNAL +
FFERR_EFFECTTYPEMISMATCH +
+
If the method returns S_FALSE, the effect has already been downloaded to the device. +
+ @discussion It is valid to update an effect while it is playing. The semantics of such an operation are explained in the reference for FFEffectSetParameters. +*/ + +extern HRESULT +FFEffectDownload( + FFEffectObjectReference effectReference + ); + +/*! @function FFEffectEscape + @abstract Sends a hardware-specific command to the driver. + @param effectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @param pFFEffectEscape FFEFFESCAPE structure that describes the command to be sent. On success, the cbOutBuffer member contains the number of bytes of the output buffer used. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
FFERR_UNSUPPORTED +
+
Other device-specific error codes are also possible. Ask the hardware manufacturer for details +
+ @discussion Because each driver implements different escapes, it is the application's responsibility to ensure that it is sending the escape to the correct driver. +*/ + +extern HRESULT +FFEffectEscape( + FFEffectObjectReference effectReference, + FFEFFESCAPE * pFFEffectEscape + ); + +/*! @function FFEffectGetEffectStatus + @abstract Sends a hardware-specific command to the driver. + @param effectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @param pFlags Pointer to status flags for the effect. The value can be 0 or one or more of the following constants: +
+
FFEGES_PLAYING +
The effect is playing. +
+
FFEGES_EMULATED +
The effect is emulated. +
+ @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
+ @discussion +*/ + +extern HRESULT +FFEffectGetEffectStatus( + FFEffectObjectReference effectReference, + FFEffectStatusFlag * pFlags + ); + +/*! @function FFEffectGetParameters + @abstract Retrieves information about an effect. + @param efffectRef An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @param pFFEffect Address of a FFEFFECT structure that receives effect information. The dwSize member must be filled in by the application before calling this method. + @param flags Flags that specify which parts of the effect information are to be retrieved. The value can be 0 or one or more of the following constants: +
+
FFEP_ALLPARAMS +
The union of all other FFEP_* flags, indicating that all members of the FFEFFECT structure are being requested. +
+
FFEP_AXES +
The cAxes and rgdwAxes members should receive data. The cAxes member on entry contains the size (in DWORDs) of the buffer pointed to by the rgdwAxes member. If the buffer is too small, the method returns FFERR_MOREDATA and sets cAxes to the necessary size of the buffer. +
+
FFEP_DIRECTION +
The cAxes and rglDirection members should receive data. The cAxes member on entry contains the size (in DWORDs) of the buffer pointed to by the rglDirection member. If the buffer is too small, the GetParameters method returns FFERR_MOREDATA and sets cAxes to the necessary size of the buffer. +
The dwFlags member must include at least one of the coordinate system flags (FFEFF_CARTESIAN, FFEFF_POLAR, or FFEFF_SPHERICAL). The API returns the direction of the effect in one of the coordinate systems you specified, converting between coordinate systems as necessary. On exit, exactly one of the coordinate system flags is set in the dwFlags member, indicating which coordinate system the FF API used. In particular, passing all three coordinate system flags retrieves the coordinates in exactly the same format in which they were set. +
+
FFEP_DURATION +
The dwDuration member should receive data. +
+
FFEP_ENVELOPE +
The lpEnvelope member points to a FFENVELOPE structure that should receive data. If the effect does not have an envelope associated with it, the lpEnvelope member is set to NULL. +
+
FFEP_GAIN +
The dwGain member should receive data. +
+
FFEP_SAMPLEPERIOD +
The dwSamplePeriod member should receive data. +
+
FFEP_STARTDELAY +
The dwStartDelay member should receive data. +
+
FFEP_TRIGGERBUTTON +
The dwTriggerButton member should receive data. +
+
FFEP_TRIGGERREPEATINTERVAL +
The dwTriggerRepeatInterval member should receive data. +
+
FFEP_TYPESPECIFICPARAMS +
The lpvTypeSpecificParams member points to a buffer whose size is specified by the cbTypeSpecificParams member. On return, the buffer is filled in with the type-specific data associated with the effect, and the cbTypeSpecificParams member contains the number of bytes copied. If the buffer supplied by the application is too small to contain all the type-specific data, the method returns FFERR_MOREDATA, and the cbTypeSpecificParams member contains the required size of the buffer in bytes. +
+ @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
FFERR_MOREDATA +
+ @discussion Common errors resulting in a FFERR_INVALIDPARAM error include not setting the dwSize member of the FFEFFECT structure, passing invalid flags, or not setting up the members in the FFEFFECT structure properly in preparation for receiving the effect information. +*/ + +extern HRESULT +FFEffectGetParameters( + FFEffectObjectReference effectReference, + FFEFFECT * pFFEffect, + FFEffectParameterFlag flags + ); + +/*! @function FFEffectSetParameters + @abstract Sets the characteristics of an effect. + @param efffectRef An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @param pFFEffect Address of a FFEFFECT structure that contains effect information. The dwSize member must be filled in by the application before calling this method, as well as any members specified by corresponding bits in the flags parameter. + @param flags Flags that specify which portions of the effect information are to be set and how the downloading of the parameters should be handled. The value can be 0 or one or more of the following constants: +
+
FFEP_AXES +
The cAxes and rgdwAxes members contain data. +
+
FFEP_DIRECTION +
The cAxes and rglDirection members contain data. The dwFlags member specifies (with FFEFF_CARTESIAN or FFEFF_POLAR) the coordinate system in which the values should be interpreted. +
+
FFEP_DURATION +
The dwDuration member contains data. +
+
FFEP_ENVELOPE +
The lpEnvelope member points to a FFENVELOPE structure that contains data. To detach any existing envelope from the effect, pass this flag and set the lpEnvelope member to NULL. +
+
FFEP_GAIN +
The dwGain member contains data. +
+
FFEP_NODOWNLOAD +
Suppress the automatic FFEffect_Download that is normally performed after the parameters are updated. +
+
FFEP_NORESTART +
Suppress the stopping and restarting of the effect to change parameters. See Remarks. +
+
FFEP_SAMPLEPERIOD +
The dwSamplePeriod member contains data. +
+
FFEP_START +
The effect is to be started (or restarted if it is currently playing) after the parameters are updated. By default, the play state of the effect is not altered. +
+
FFEP_STARTDELAY +
The dwStartDelay member contains data. +
+
FFEP_TRIGGERBUTTON +
The dwTriggerButton member contains data. +
+
+
The dwTriggerRepeatInterval member contains data. +
+
FFEP_TYPESPECIFICPARAMS +
The lpvTypeSpecificParams and cbTypeSpecificParams members of the FFEFFECT structure contain the address and size of type-specific data for the effect. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_UNSUPPORTEDAXIS +
FFERR_OUTOFMEMORY +
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_INVALIDDOWNLOADID +
FFERR_INTERNAL +
FFERR_EFFECTTYPEMISMATCH +
+ @discussion The FFEffectSetParameters method automatically downloads the effect, but this behavior can be suppressed by setting the FFEP_NODOWNLOAD flag. If automatic download has been suppressed, you can manually download the effect by invoking the FFEffectDownload method. +
+
If the effect is playing while the parameters are changed, the new parameters take effect as if they were the parameters when the effect started. +
+
For example, suppose a periodic effect with a duration of three seconds is started. After two seconds, the direction of the effect is changed. The effect then continues for one additional second in the new direction. The envelope, phase, amplitude, and other parameters of the effect continue smoothly, as if the direction had not changed. +
+
In the same situation, if after two seconds the duration of the effect were changed to 1.5 seconds, the effect would stop. +
+
Normally, if the driver cannot update the parameters of a playing effect, the driver is permitted to stop the effect, update the parameters, and then restart the effect. Passing the FFEP_NORESTART flag suppresses this behavior. If the driver cannot update the parameters of an effect while it is playing, the error code FFERR_EFFECTPLAYING is returned, and the parameters are not updated. +
+
No more than one of the FFEP_NODOWNLOAD, FFEP_START, and FFEP_NORESTART flags should be set. (It is also valid to pass none of them.) +
+
These three flags control download and playback behavior as follows: +
+
If FFEP_NODOWNLOAD is set, the effect parameters are updated but not downloaded to the device. +
+
If the FFEP_START flag is set, the effect parameters are updated and downloaded to the device, and the effect is started just as if the FFEffect_Start method had been called with the dwIterations parameter set to 1 and with no flags. (Combining the update with FFEP_START is slightly faster than calling Start separately, because it requires less information to be transmitted to the device.) +
+
If neither FFEP_NODOWNLOAD nor FFEP_START is set and the effect is not playing, the parameters are updated and downloaded to the device. +
+
If neither FFEP_NODOWNLOAD nor FFEP_START is set and the effect is playing, the parameters are updated if the device supports on-the-fly updating. Otherwise the behavior depends on the state of the FFEP_NORESTART flag. If it is set, the error code FFERR_EFFECTPLAYING is returned. If it is clear, the effect is stopped, the parameters are updated, and the effect is restarted. + +*/ + +extern HRESULT +FFEffectSetParameters( + FFEffectObjectReference effectReference, + FFEFFECT * pFFEffect, + FFEffectParameterFlag flags + ); + +/*! @function FFEffectStart + @abstract Begins playing an effect. If the effect is already playing, it is restarted from the beginning. If the effect has not been downloaded or has been modified since its last download, it is downloaded before being started. This default behavior can be suppressed by passing the FFES_NODOWNLOAD flag. + @param efffectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @param iterations Number of times to play the effect in sequence. The envelope is re-articulated with each iteration. +
+
To play the effect exactly once, pass 1. To play the effect repeatedly until explicitly stopped, pass INFINITE. To play the effect until explicitly stopped without re-articulating the envelope, modify the effect parameters with the FFEffect_SetParameters method, and change the dwDuration member to INFINITE. + @param flags Flags that describe how the effect should be played by the device. The value can be 0 or one or more of the following values: +
+
FFES_SOLO +
All other effects on the device should be stopped before the specified effect is played. If this flag is omitted, the effect is mixed with existing effects already started on the device. +
+
FFES_NODOWNLOAD +
Do not automatically download the effect. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_INVALIDDOWNLOADID +
FFERR_INTERNAL +
FFERR_EFFECTTYPEMISMATCH +
FFERR_GENERIC +
+ @discussion Not all devices support multiple iterations. +*/ + +extern HRESULT +FFEffectStart( + FFEffectObjectReference effectReference, + UInt32 iterations, + FFEffectStartFlag flags + ); + +/*! @function FFEffectStop + @abstract Stops playing an effect. + @param effectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
FFERR_GENERIC +
FFERR_INTERNAL +
FFERR_INVALIDDOWNLOADID +
+ @discussion +*/ + +extern HRESULT +FFEffectStop( + FFEffectObjectReference effectReference + ); + +/*! @function FFEffectUnload + @abstract Removes the effect from the device. If the effect is playing, it is automatically stopped before it is unloaded. + @param effectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
FFERR_GENERIC +
FFERR_INTERNAL +
FFERR_INVALIDDOWNLOADID +
+ @discussion +*/ +extern HRESULT +FFEffectUnload( + FFEffectObjectReference effectReference + ); + + +#ifdef __cplusplus +} +#endif + +#endif // _FORCEFEEDBACK_H_ + + + + + + + diff --git a/Frameworks/ForceFeedback.framework/Headers/ForceFeedbackConstants.h b/Frameworks/ForceFeedback.framework/Headers/ForceFeedbackConstants.h new file mode 100755 index 0000000..30e5222 --- /dev/null +++ b/Frameworks/ForceFeedback.framework/Headers/ForceFeedbackConstants.h @@ -0,0 +1,572 @@ +//----------------------------------------------------------------------------- +// File: ForceFeedbackConstants.h +// Contains: Public interfaces for ForceFeedback technology. +// Copyright: © 2002 by Apple Computer, Inc. All rights reserved. +// +//----------------------------------------------------------------------------- + +#ifndef _FORCEFEEDBACKCONSTANTS_H_ +#define _FORCEFEEDBACKCONSTANTS_H_ + +#if PRAGMA_ONCE +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! @header ForceFeedbackConstants.h + @abstract Constants used in the public interfaces to the Force Feedback implementation in Mac OS X. + @discussion This header file contains the Effect type UUIDs, type definitions used in the API, force feedback + constants and error values used by the API. + +*/ + +//----------------------------------------------------------------------------- +// General defines +//----------------------------------------------------------------------------- +#if !defined( DWORD ) +typedef UInt32 DWORD; +typedef DWORD* LPDWORD; +#endif +#if !defined( LONG ) +typedef SInt32 LONG; +typedef LONG* LPLONG; +#endif + +#define FF_INFINITE 0xFFFFFFFF + +#define FF_DEGREES 100 +#define FF_FFNOMINALMAX 10000 +#define FF_SECONDS 1000000 + + +//----------------------------------------------------------------------------- +// Effect type UUIDs +//----------------------------------------------------------------------------- + +// E559C460-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_ConstantForce_ID + @discussion UUID for a constant force effect type + */ +#define kFFEffectType_ConstantForce_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x60, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C461-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_RampForce_ID + @discussion UUID for a ramp force effect type + */ +#define kFFEffectType_RampForce_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x61, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C462-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Square_ID + @discussion UUID for a square wave effect type + */ +#define kFFEffectType_Square_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x62, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C463-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Sine_ID + @discussion UUID for a sine wave effect type + */ +#define kFFEffectType_Sine_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x63, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C464-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Sine_ID + @discussion UUID for a sine wave effect type + */ +#define kFFEffectType_Triangle_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x64, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C465-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_SawtoothUp_ID + @discussion UUID for a upwards sawtooth wave effect type + */ +#define kFFEffectType_SawtoothUp_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x65, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C466-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_SawtoothDown_ID + @discussion UUID for a downwards sawtooth wave effect type + */ +#define kFFEffectType_SawtoothDown_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x66, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C467-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Spring_ID + @discussion UUID for a spring effect type + */ +#define kFFEffectType_Spring_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x67, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C468-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Damper_ID + @discussion UUID for a damper effect type + */ +#define kFFEffectType_Damper_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x68, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C469-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Inertia_ID + @discussion UUID for an inertia effect type + */ +#define kFFEffectType_Inertia_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x69, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C46A-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Friction_ID + @discussion UUID for a friction effect type + */ +#define kFFEffectType_Friction_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x6A, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C46B-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_CustomForce_ID + @discussion UUID for a custom force effect type + */ +#define kFFEffectType_CustomForce_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x6B, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +//----------------------------------------------------------------------------- +// Effect definition constants +//----------------------------------------------------------------------------- + +// FFEFFECT.dwFlags constants +// IMPORTANT NOTE: OBJECT IDS cannot be used to identify trigger buttons +// in FFEFFECT.dwTriggerButton, and output axes in FFEFFECT.rgdwAxes[n]. +// Please use object offsets (FFJOFS_* constants), the only supported method. +// #define FFEFF_OBJECTIDS 0x00000001 +#define FFEFF_OBJECTOFFSETS 0x00000002 + +typedef UInt32 FFCoordinateSystemFlag; +enum +{ + FFEFF_CARTESIAN = 0x00000010, + FFEFF_POLAR = 0x00000020, + FFEFF_SPHERICAL = 0x00000040 +}; + +// Effect Parameter flags for use in calls to FFEffectGetParameters() and FFEffectSetParameters() +// +typedef UInt32 FFEffectParameterFlag; +enum +{ + FFEP_DURATION = 0x00000001, + FFEP_SAMPLEPERIOD = 0x00000002, + FFEP_GAIN = 0x00000004, + FFEP_TRIGGERBUTTON = 0x00000008, + FFEP_TRIGGERREPEATINTERVAL = 0x00000010, + FFEP_AXES = 0x00000020, + FFEP_DIRECTION = 0x00000040, + FFEP_ENVELOPE = 0x00000080, + FFEP_TYPESPECIFICPARAMS = 0x00000100, + FFEP_STARTDELAY = 0x00000200, + FFEP_ALLPARAMS = 0x000003FF, + FFEP_START = 0x20000000, + FFEP_NORESTART = 0x40000000, + FFEP_NODOWNLOAD = 0x80000000, + FFEB_NOTRIGGER = 0xFFFFFFFF +}; + +// Effect Parameter flags for use in calls to FFEffectStart() +// +typedef UInt32 FFEffectStartFlag; +enum +{ + FFES_SOLO = 0x00000001, + FFES_NODOWNLOAD = 0x80000000 +}; + +// Effect Parameter flags for use in calls to FFEffectGetEffectStatus() +// +typedef UInt32 FFEffectStatusFlag; +enum +{ + FFEGES_NOTPLAYING = 0x00000000, + FFEGES_PLAYING = 0x00000001, + FFEGES_EMULATED = 0x00000002 +}; + +// command flags for FFDeviceSendForceFeedbackCommand() +// +typedef UInt32 FFCommandFlag; +enum +{ + FFSFFC_RESET = 0x00000001, + FFSFFC_STOPALL = 0x00000002, + FFSFFC_PAUSE = 0x00000004, + FFSFFC_CONTINUE = 0x00000008, + FFSFFC_SETACTUATORSON = 0x00000010, + FFSFFC_SETACTUATORSOFF = 0x00000020 +}; + +// device state flags returned by FFDeviceGetForceFeedbackState() +// +typedef UInt32 FFState; +enum +{ + FFGFFS_EMPTY = 0x00000001, + FFGFFS_STOPPED = 0x00000002, + FFGFFS_PAUSED = 0x00000004, + FFGFFS_ACTUATORSON = 0x00000010, + FFGFFS_ACTUATORSOFF = 0x00000020, + FFGFFS_POWERON = 0x00000040, + FFGFFS_POWEROFF = 0x00000080, + FFGFFS_SAFETYSWITCHON = 0x00000100, + FFGFFS_SAFETYSWITCHOFF = 0x00000200, + FFGFFS_USERFFSWITCHON = 0x00000400, + FFGFFS_USERFFSWITCHOFF = 0x00000800, + FFGFFS_DEVICELOST = 0x80000000 +}; + + +// axis and button "field offsets", +// used in +// FFEFFECT.dwTriggerButton +// FFEFFECT.rgdwAxes[n] +#define FFJOFS_X 0 +#define FFJOFS_Y 4 +#define FFJOFS_Z 8 +#define FFJOFS_RX 12 +#define FFJOFS_RY 16 +#define FFJOFS_RZ 20 +#define FFJOFS_SLIDER(n) (24 + (n) * sizeof(LONG)) +#define FFJOFS_POV(n) (32 + (n) * sizeof(DWORD)) +#define FFJOFS_BUTTON(n) (48 + (n)) +#define FFJOFS_BUTTON0 FFJOFS_BUTTON(0) +#define FFJOFS_BUTTON1 FFJOFS_BUTTON(1) +#define FFJOFS_BUTTON2 FFJOFS_BUTTON(2) +#define FFJOFS_BUTTON3 FFJOFS_BUTTON(3) +#define FFJOFS_BUTTON4 FFJOFS_BUTTON(4) +#define FFJOFS_BUTTON5 FFJOFS_BUTTON(5) +#define FFJOFS_BUTTON6 FFJOFS_BUTTON(6) +#define FFJOFS_BUTTON7 FFJOFS_BUTTON(7) +#define FFJOFS_BUTTON8 FFJOFS_BUTTON(8) +#define FFJOFS_BUTTON9 FFJOFS_BUTTON(9) +#define FFJOFS_BUTTON10 FFJOFS_BUTTON(10) +#define FFJOFS_BUTTON11 FFJOFS_BUTTON(11) +#define FFJOFS_BUTTON12 FFJOFS_BUTTON(12) +#define FFJOFS_BUTTON13 FFJOFS_BUTTON(13) +#define FFJOFS_BUTTON14 FFJOFS_BUTTON(14) +#define FFJOFS_BUTTON15 FFJOFS_BUTTON(15) +#define FFJOFS_BUTTON16 FFJOFS_BUTTON(16) +#define FFJOFS_BUTTON17 FFJOFS_BUTTON(17) +#define FFJOFS_BUTTON18 FFJOFS_BUTTON(18) +#define FFJOFS_BUTTON19 FFJOFS_BUTTON(19) +#define FFJOFS_BUTTON20 FFJOFS_BUTTON(20) +#define FFJOFS_BUTTON21 FFJOFS_BUTTON(21) +#define FFJOFS_BUTTON22 FFJOFS_BUTTON(22) +#define FFJOFS_BUTTON23 FFJOFS_BUTTON(23) +#define FFJOFS_BUTTON24 FFJOFS_BUTTON(24) +#define FFJOFS_BUTTON25 FFJOFS_BUTTON(25) +#define FFJOFS_BUTTON26 FFJOFS_BUTTON(26) +#define FFJOFS_BUTTON27 FFJOFS_BUTTON(27) +#define FFJOFS_BUTTON28 FFJOFS_BUTTON(28) +#define FFJOFS_BUTTON29 FFJOFS_BUTTON(29) +#define FFJOFS_BUTTON30 FFJOFS_BUTTON(30) +#define FFJOFS_BUTTON31 FFJOFS_BUTTON(31) + +// defines for FFDeviceGetForceFeedbackProperty() and FFDeviceSetForceFeedbackProperty() +// +typedef UInt32 FFProperty; +enum +{ + FFPROP_FFGAIN = 1, + FFPROP_AUTOCENTER = 3 +}; + +// flags for FFDeviceSetCooperativeLevel() +// +typedef UInt32 FFCooperativeLevelFlag; +enum +{ + FFSCL_EXCLUSIVE = 0x00000001, + FFSCL_NONEXCLUSIVE = 0x00000002, + FFSCL_FOREGROUND = 0x00000004, + FFSCL_BACKGROUND = 0x00000008 +}; + +// types used in FFCAPABILITIES structure +// +typedef UInt32 FFCapabilitiesEffectType; +enum +{ + FFCAP_ET_CONSTANTFORCE = 0x00000001, + FFCAP_ET_RAMPFORCE = 0x00000002, + FFCAP_ET_SQUARE = 0x00000004, + FFCAP_ET_SINE = 0x00000008, + FFCAP_ET_TRIANGLE = 0x00000010, + FFCAP_ET_SAWTOOTHUP = 0x00000020, + FFCAP_ET_SAWTOOTHDOWN = 0x00000040, + FFCAP_ET_SPRING = 0x00000080, + FFCAP_ET_DAMPER = 0x00000100, + FFCAP_ET_INERTIA = 0x00000200, + FFCAP_ET_FRICTION = 0x00000400, + FFCAP_ET_CUSTOMFORCE = 0x00000800 +}; + +typedef UInt32 FFCapabilitiesEffectSubType; +enum +{ + FFCAP_ST_KINESTHETIC = 1, + FFCAP_ST_VIBRATION = 2 +}; + + +//----------------------------------------------------------------------------- +// Error return values +//----------------------------------------------------------------------------- + +/*! + @defined FF_OK + @discussion The operation completed successfully. +*/ +#define FF_OK S_OK + +/*! + @defined FF_FALSE + @discussion The operation did not complete successfully. +*/ +#define FF_FALSE S_FALSE + +/*! + @defined FF_DOWNLOADSKIPPED + * @discussion + * The parameters of the effect were successfully updated by + * FFEffectSetParameters, but the effect was not + * downloaded because the FFEP_NODOWNLOAD flag was passed. + */ +#define FF_DOWNLOADSKIPPED ((HRESULT)0x00000003L) + +/*! + @defined FF_EFFECTRESTARTED + * @discussion + * The parameters of the effect were successfully updated by + * FFEffectSetParameters, but in order to change + * the parameters, the effect needed to be restarted. + */ +#define FF_EFFECTRESTARTED ((HRESULT)0x00000004L) + +/*! + @defined FF_TRUNCATED + * @discussion + * The parameters of the effect were successfully updated by + * FFEffectSetParameters, but some of them were + * beyond the capabilities of the device and were truncated. + */ +#define FF_TRUNCATED ((HRESULT)0x00000008L) + +/*! + @defined FF_TRUNCATEDANDRESTARTED + * @discussion + * Equal to FF_EFFECTRESTARTED | FF_TRUNCATED. + */ +#define FF_TRUNCATEDANDRESTARTED ((HRESULT)0x0000000CL) + +/*! + @defined FFERR_DEVICENOTREG + * @discussion + * The device or device instance or effect is not registered. + */ +#define FFERR_DEVICENOTREG REGDB_E_CLASSNOTREG + +/*! + @defined FFERR_INVALIDPARAM + * @discussion + * An invalid parameter was passed to the returning function, + * or the object was not in a state that admitted the function + * to be called. + */ +#define FFERR_INVALIDPARAM E_INVALIDARG + +/*! + @defined FFERR_NOINTERFACE + * @discussion + * The specified interface is not supported by the object + */ +#define FFERR_NOINTERFACE E_NOINTERFACE + +/*! + @defined FFERR_GENERIC + * @discussion + * An undetermined error occurred. + */ +#define FFERR_GENERIC E_FAIL + +/*! + @defined FFERR_OUTOFMEMORY + * @discussion + * Couldn't allocate sufficient memory to complete the caller's request. + */ +#define FFERR_OUTOFMEMORY E_OUTOFMEMORY + +/*! + @defined FFERR_UNSUPPORTED + * @discussion + * The function called is not supported at this time + */ +#define FFERR_UNSUPPORTED E_NOTIMPL + +#ifndef E_PENDING +/*! + @defined E_PENDING + * @discussion + * Data is not yet available. + */ +#define E_PENDING 0x8000000AL +#endif + +/*! + @defined FFERR_DEVICEFULL + * @discussion + * The device is full. + */ +#define FFERR_DEVICEFULL 0x80040201L + +/*! + @defined FFERR_MOREDATA + * @discussion + * Not all the requested information fit into the buffer. + */ +#define FFERR_MOREDATA 0x80040202L + +/*! + @defined FFERR_NOTDOWNLOADED + * @discussion + * The effect is not downloaded. + */ +#define FFERR_NOTDOWNLOADED 0x80040203L + +/*! + @defined FFERR_HASEFFECTS + * @discussion + * The device cannot be reinitialized because there are still effects + * attached to it. + */ +#define FFERR_HASEFFECTS 0x80040204L + +/*! + @defined FFERR_INCOMPLETEEFFECT + * @discussion + * The effect could not be downloaded because essential information + * is missing. For example, no axes have been associated with the + * effect, or no type-specific information has been created. + */ +#define FFERR_INCOMPLETEEFFECT 0x80040206L + +/*! + @defined FFERR_EFFECTPLAYING + * @discussion + * An attempt was made to modify parameters of an effect while it is + * playing. Not all hardware devices support altering the parameters + * of an effect while it is playing. + */ +#define FFERR_EFFECTPLAYING 0x80040208L + +/*! + @defined FFERR_UNPLUGGED + * @discussion + * The operation could not be completed because the device is not + * plugged in. + */ +#define FFERR_UNPLUGGED 0x80040209L + + +// +// Mac OS X specific +// + +/*! + @defined FFERR_INVALIDDOWNLOADID + * @discussion + * The effect index provided by the API in downloadID is not recognized by the + * IOForceFeedbackLib driver. + */ +#define FFERR_INVALIDDOWNLOADID 0x80040300 + +/*! + @defined FFERR_DEVICEPAUSED + * @discussion + * When the device is paused via a call to FFDeviceSendForceFeedbackCommand(), + * other operations such as modifying existing effect parameters and creating + * new effects are not allowed. + */ +#define FFERR_DEVICEPAUSED 0x80040301 + +/*! + @defined FFERR_INTERNAL + * @discussion + * The IOForceFededbackLib driver has detected an internal fault. Often this + * occurs because of an unexpected internal code path. + */ +#define FFERR_INTERNAL 0x80040302 + +/*! + @defined FFERR_EFFECTTYPEMISMATCH + * @discussion + * The IOForceFededbackLib driver has received an effect modification request + * whose basic type does not match the defined effect type for the given effect. + */ +#define FFERR_EFFECTTYPEMISMATCH 0x80040303 + +/*! + @defined FFERR_UNSUPPORTEDAXIS + * @discussion + * The effect includes one or more axes that the device does not support. + */ +#define FFERR_UNSUPPORTEDAXIS 0x80040304 + +/*! + @defined FFERR_NOTINITIALIZED + * @discussion + * This object has not been initialized + */ +#define FFERR_NOTINITIALIZED 0x80040305 + +/*! + @defined FFERR_EFFECTTYPENOTSUPPORTED + * @discussion + * The effect type requested is not explicitly supported by the particular device. + */ +#define FFERR_EFFECTTYPENOTSUPPORTED 0x80040306 + +/*! + @defined FFERR_DEVICERELEASED + * @discussion + * The device has been released. + */ +#define FFERR_DEVICERELEASED 0x80040307 + +#ifdef __cplusplus +} +#endif + +#endif // _FORCEFEEDBACKCONSTANTS_H_ + diff --git a/Frameworks/ForceFeedback.framework/Headers/IOForceFeedbackLib.h b/Frameworks/ForceFeedback.framework/Headers/IOForceFeedbackLib.h new file mode 100755 index 0000000..7bce10c --- /dev/null +++ b/Frameworks/ForceFeedback.framework/Headers/IOForceFeedbackLib.h @@ -0,0 +1,447 @@ +//----------------------------------------------------------------------------- +// File: IOForceFeedbackLib.h +// Contains: Public interfaces for the Force Feedback Plugin architecture . +// Copyright: © 2002 by Apple Computer, Inc. All rights reserved. +// +//----------------------------------------------------------------------------- + +#ifndef _IOFORCEFEEDBACKLIB_H +#define _IOFORCEFEEDBACKLIB_H + +#if PRAGMA_ONCE +#pragma once +#endif + +/*! @header IOForceFeedbackLib.h + @abstract Public Interfaces and constants used to develop Force Feedback plugIns. + @discussion A force feedback device manufacturer might need to implement a plug in + to allow the Force Feedback Library to control the device. This header + file describes the functions that need to be implemented. This interface definition + follows Microsoft Windoes IDirectInputEffectDriver definition wherever it makes sense to do so. + Certain functions may contain more or fewer parameters than the Windows version + +*/ +#include + +__BEGIN_DECLS +#include +#if COREFOUNDATION_CFPLUGINCOM_SEPARATE +#include +#endif + +#include +#include +#include + +//==================================================================================================================== +// The Version of the FF PlugIn API +//==================================================================================================================== +// +enum { + kFFPlugInAPIMajorRev = 1, + kFFPlugInAPIMinorAndBugRev = 0, + kFFPlugInAPIStage = finalStage, + kFFPlugInAPINonRelRev = 0 +}; + +//==================================================================================================================== +// Defines +//==================================================================================================================== +// + +#define FFDEVICESTATE ForceFeedbackDeviceState +#define PFFDEVICESTATE ForceFeedbackDeviceStatePtr + + +// F4545CE5-BF5B-11D6-A4BB-0003933E3E3E +#define kIOForceFeedbackLibTypeID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xF4, 0x54, 0x5C, 0xE5, 0xBF, 0x5B, 0x11, 0xD6, \ + 0xA4, 0xBB, 0x00, 0x03, 0x93, 0x3E, 0x3E, 0x3E) + +// 1C7C5850-BB6A-11D6-B75F-003065FBE6B0 +#define kIOForceFeedbackDeviceInterfaceID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0x1C, 0x7C, 0x58, 0x50, 0xBB, 0x6A, 0x11, 0xD6, \ + 0xB7, 0x5F, 0x00, 0x30, 0x65, 0xFB, 0xE6, 0xB0) + + +//==================================================================================================================== +// Structs +//==================================================================================================================== +// +struct ForceFeedbackDeviceState +{ + UInt32 dwSize; + UInt32 dwState; + UInt32 dwLoad; + +}; + +typedef struct ForceFeedbackDeviceState ForceFeedbackDeviceState; +typedef ForceFeedbackDeviceState * ForceFeedbackDeviceStatePtr; + + +struct ForceFeedbackVersion +{ + NumVersion apiVersion; + NumVersion plugInVersion; +}; + +typedef struct ForceFeedbackVersion ForceFeedbackVersion; +typedef ForceFeedbackVersion * ForceFeedbackVersionPtr; + +//==================================================================================================================== +// Types +//==================================================================================================================== +// +typedef UInt32 FFEffectDownloadID; + + +//==================================================================================================================== +// +// ForceFeedback Device Interface Functions available in version 1.0 of architecture +// +//==================================================================================================================== +// +#define IOFORCEFEEDBACKDEVICE_FUNCS_100 \ + \ + HRESULT (*ForceFeedbackGetVersion)( void * self, \ + ForceFeedbackVersion * version); \ + \ + HRESULT (*InitializeTerminate)( void * self, \ + NumVersion forceFeedbackAPIVersion,\ + io_object_t hidDevice, \ + bool begin ); \ + \ + HRESULT (*DestroyEffect)( void * self, \ + FFEffectDownloadID downloadID ); \ + \ + HRESULT (*DownloadEffect)( void * self, \ + CFUUIDRef effectType, \ + FFEffectDownloadID * pDownloadID, \ + FFEFFECT * pEffect, \ + FFEffectParameterFlag flags ); \ + \ + HRESULT (*Escape)( void * self, \ + FFEffectDownloadID downloadID, \ + FFEFFESCAPE * pEscape ); \ + \ + HRESULT (*GetEffectStatus)( void * self, \ + FFEffectDownloadID downloadID, \ + FFEffectStatusFlag * pStatusCode ); \ + \ + HRESULT (*GetForceFeedbackCapabilities)( void * self, \ + FFCAPABILITIES * pCapabilities ); \ + \ + HRESULT (*GetForceFeedbackState)( void * self, \ + ForceFeedbackDeviceState * pDeviceState ); \ + \ + HRESULT (*SendForceFeedbackCommand)( void * self, \ + FFCommandFlag state ); \ + \ + HRESULT (*SetProperty)( void * self, \ + FFProperty property, \ + void * pValue ); \ + \ + HRESULT (*StartEffect)( void * self, \ + FFEffectDownloadID downloadID, \ + FFEffectStartFlag mode, \ + UInt32 iterations ); \ + \ + HRESULT (*StopEffect)( void * self, \ + FFEffectDownloadID downloadID ); + +//==================================================================================================================== +// +// END OF DeviceInterface Functions available in version 1.0 of this API +// +//==================================================================================================================== +// +struct IOForceFeedbackDeviceInterface { + IUNKNOWN_C_GUTS; + IOFORCEFEEDBACKDEVICE_FUNCS_100 +}; + +typedef struct IOForceFeedbackDeviceInterface IOForceFeedbackDeviceInterface; +typedef IOForceFeedbackDeviceInterface * IOForceFeedbackDeviceInterfacePtr; + + +//==================================================================================================================== +// +// ¥¥¥¥¥ The following is #ifdef out. It is here so that we can header doc this file without intruding in its +// ¥¥¥¥¥ readability. +// +//==================================================================================================================== +// +#if 0 + +struct IOForceFeedbackDeviceInterface { + IUNKNOWN_C_GUTS; + +/*! @function ForceFeedbackGetVersion + @abstract This function is used to determine driver and API version information. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param version Pointer to ForceFeedbackVersion structure that is to receive the required info. See the structure description for details. + @result Returns FF_OK if successful, or an error value otherwise. +*/ + HRESULT (*ForceFeedbackGetVersion) (void * self, ForceFeedbackVersion * version); + + +/*! @function InitializeTerminate + @abstract This function is used to "create and destroy" particular device instances. It provides the FF plug-in driver with all the necessary start-up parameters. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param forceFeedbackAPIVersion The version number of FF API that loaded the effect driver. The plugIn should check that the major version of the forceFeedbackAPI version is the same as the major version of the API at the time the plugIn was compiled. If the major versions are different, then the plugIn API has changed and the plugIn will NOT be compatible with it. +
+If begin is false, this parameter is ignored. + @param hidDevice A device object that can be used by the FF plug-in to establish a connection to and communicate with the device. The caller will release the hidDevice device object with a call to IOObjectRelease() once the FF plug-in completes its InitializeTerminate processing, so a FF plug-in implementation should not make a copy of the io_object_t variable with the intention of using it outside the context of this call. +
+If begin is false, this parameter is ignored. (You can pass NULL.) + @param begin Nonzero if access to the device is beginning. Zero if the access to the device is ending. The FF API will call InitializeTerminate( begin=TRUE) when a FF device is first selected for use, and InitializeTerminate( begin=false) when the FF device is no longer needed. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INVALIDPARAM +
FFERR_NOINTERFACE +
FFERR_OUTOFMEMORY +
+*/ + HRESULT (*InitializeTerminate)(void * self, NumVersion forceFeedbackAPIVersion, io_object_t hidDevice, bool begin ); + + +/*! @function DestroyEffect + @abstract This function commands the device to "destroy" a currently downloaded effect. The effect ID and any data that is associated with the effect are freed and available for reallocation. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param downloadID Indicates the effect ID that was obtained from the device when the effect was downloaded. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INVALIDDOWNLOADID +
FFERR_GENERIC +
FFERR_INTERNAL +
+*/ + HRESULT (*DestroyEffect)(void * self, FFEffectDownloadID downloadID ); + + +/*! @function DownloadEffect + @abstract This function sends an effect to the device. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param effectType Indicates the type of effect being created. Valid UUIDs are listed as kFFEffectType_* constants in the ForceFeedbackConstants.h file. (Supported effect types include Sine, Square, Triangle, SawtoothUp, SawtoothDown, Constant, Spring, Damper, etc.). + @param pDownloadID On entry, this parameter points to the handle of the effect being downloaded. If the parameter points to a zero, then a new effect is downloaded. On exit, the FFEffectDownloadID pointed to by this parameter contains the new effect handle. On failure, the FFEffectDownloadID pointed to by this parameter is set to zero if the effect is lost, or left alone if the effect is still valid with its old parameters. Note that zero is never a valid effect handle. + @param pEffect The new parameters for the effect. +
+IMPORTANT NOTE: Unlike the IDirectInputEffectDriver specification, the axis and button values are NOT converted to object identifiers before they are handed over to the driver. In this case, the only supported method used to assign triggers and output axes is through object offsets, defined by the FFJOFS_* constants. Therefore, if a button is assigned to trigger an effect, FFEFFECT.dwTriggerButton will contain a constant of the form FFJOFS_BUTTONn. Similarly, output axes will be identified in FFEFFECT.rgdwAxes[n] as FFJOFS_X, FFJOFS_Y, etc. + @param flags Specifies which portions of the effect information have changed from the effect already on the device. This information is passed to drivers to allow for the optimization of effect modification. If an effect is being modified, a driver may be able to update the effect in its original position and transmit to the device only the information that has changed. Drivers are not, however, required to implement this optimization. All members of the FFEFFECT structure that are pointed to by the pEffect parameter are valid, and a driver may choose simply to update all parameters of the effect at each download. There may be zero, one, or more of the following: +
+
FFEP_DURATION +
Indicates the dwDuration member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_SAMPLEPERIOD +
Indicates the dwSamplePeriod member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_GAIN +
Indicates the dwGain member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_TRIGGERBUTTON +
Indicates the dwTriggerButton member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_TRIGGERREPEATINTERVAL +
Indicates the dwTriggerRepeatInterval member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_AXES +
Indicates the cAxes and rgdwAxes members of the FFEFFECT structure are being downloaded for the first time or have changed since their last download. +
+
FFEP_DIRECTION +
Indicates the cAxes and rglDirection members of the FFEFFECT structure are being downloaded for the first time or have changed since their last download. (The dwFlags member of the FFEFFECT structure specifies, through FFEFF_CARTESIAN or FFEFF_POLAR, the coordinate system in which the values should be interpreted.) +
+
FFEP_ENVELOPE +
Indicates the lpEnvelope member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. If this flag is set and the lpEnvelope member is a NULL pointer, then the effect is being created with no envelope, or the existing envelope is being deleted. +
+
FFEP_TYPESPECIFICPARAMS +
Indicates the cbTypeSpecificParams and lpTypeSpecificParams members of the FFEFFECT structure are being downloaded for the first time or have changed since their last download. +
+
FFEP_STARTDELAY +
Indicates the dwStartDelay member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_START +
Indicates that the effect is to be restarted from the beginning after the parameters of the effect have been updated. Note that the FFEP_NODOWNLOAD flag overrides the FFEP_START flag. +
+
FFEP_NORESTART +
If this flag is not specified, the effect device driver is permitted to restart the effect if doing so is necessary to change the specified parameters. Note that the FFEP_NODOWNLOAD and FFEP_START flags override this flag. +
+
FFEP_NODOWNLOAD +
Suppresses the automatic download that is normally performed after the parameters are updated. If this flag is set, the driver should validate parameters without performing an actual download. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_INVALIDDOWNLOADID +
FFERR_INTERNAL +
FFERR_EFFECTTYPEMISMATCH +
+*/ + HRESULT (*DownloadEffect)( void * self, CFUUIDRef effectType, FFEffectDownloadID * pDownloadID, +FFEFFECT * pEffect, FFEffectParameterFlag flags ); + + +/*! @function Escape + @abstract This function escapes to the driver. This method is called in response to an application invoking the FFEffectEscape or FFDeviceEscape methods. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param downloadID Specifies the effect at which the command is directed, or zero if the command is directed at the device itself and not any particular effect. + @param pEscape Pointer to a FFEFFESCAPE structure that describes the command to be sent. On success, the cbOutBuffer member contains the number of output buffer bytes actually used. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_UNSUPPORTED +
+*/ + HRESULT (*Escape)( void * self, FFEffectDownloadID downloadID, FFEFFESCAPE * pEscape ); + + +/*! @function GetEffectStatus + @abstract This function returns the device effect's status. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param downloadID Indicates the effect to be queried. + @param pStatusCode Receives the effect status. The FFEffectStatusFlag pointed to by this parameter should be filled in with one of the following values: +
+
FFEGES_PLAYING +
The effect is still playing. +
+
FFEGES_NOTPLAYING +
The effect is not playing. + @result Returns FF_OK. +*/ + HRESULT (*GetEffectStatus)( void * self, FFEffectDownloadID downloadID, FFEffectStatusFlag * pStatusCode ); + + +/*! @function GetForceFeedbackCapabilities + @abstract This function escapes to the driver. This method is called in response to an application invoking the FFEffectEscape or FFDevicEscape methods. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param pCapabilities Pointer to a FFCAPABILITIES structure that should be filled in with version information describing the hardware, firmware, and driver. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INTERNAL +
FFERR_NOINTERFACE +
+*/ + HRESULT (*GetForceFeedbackCapabilities)( void * self, FFCAPABILITIES * pCapabilities ); + + +/*! @function GetForceFeedbackState + @abstract This function returns the state of the device. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param pDeviceState Pointer to a ForceFeedbackDeviceState structure that receives the device state. FF API sets the dwSize member of the ForceFeedbackDeviceState structure to sizeof(ForceFeedbackDeviceState) before calling this method. + @result Returns FF_OK. +*/ + HRESULT (*GetForceFeedbackState)( void * self, ForceFeedbackDeviceState * pDeviceState ); + + +/*! @function SendForceFeedbackCommand + @abstract This function sends a command to the device. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param state Indicates the command being sent. That command can be one of the following: +
+
FFSFFC_RESET +
Indicates that playback of any active effects should be been stopped and that all effects should be removed from the device. Once the device has been reset, all effects are no longer valid and must be re-created. +
+
FFSFFC_STOPALL +
Indicates that playback of all effects should be stopped. Sending the FFSFFC_STOPALL command is equivalent to invoking the FFEffect_Stop method on all effects that are playing. If the device is in a paused state, the device driver is permitted to lose the paused state. +
+
FFSFFC_PAUSE +
Indicates that playback of all effects should be paused. When effects are paused, time "stops" until the FFSFFC_CONTINUE command is sent. For example, suppose an effect of five seconds' duration is started. After one second, all effects are paused. After two more seconds, all effects are continued. The effect should then play for four additional seconds. While a force-feedback device is paused, starting a new effect or modifying existing ones can cause the paused state to be lost. +
+
FFSFFC_CONTINUE +
Indicates that playback should be resumed at the point at which it was interrupted for those effects that were paused by a previous FFSCFFC_PAUSE command. +
+
FFSFFC_SETACTUATORSON +
Indicates that the device's force-feedback actuators should be enabled. +
+
FFSFFC_SETACTUATORSOFF +
Indicates that the device's force-feedback actuators should be disabled. If successful, force-feedback effects are "muted". Note that time continues to elapse while actuators are off. For example, suppose an effect of five seconds' duration is started. After one second, actuators are turned off. After two more seconds, actuators are turned back on. The effect should then play for two additional seconds. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INTERNAL +
FFERR_INVALIDPARAM +
+*/ + HRESULT (*SendForceFeedbackCommand)( void * self, FFCommandFlag state ); + + +/*! @function SetProperty + @abstract This function sets properties that define the device behavior. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param property The following property values are defined for a FF device: +
+
FFPROP_AUTOCENTER +
Specifies whether the actuated FF axes are self-centering. This property controls the deviceÕs Òdefault centering springÓ. +
The pValue member points to a UInt32 and can be one of the following values. +
+
0 - OFF: The device should not automatically center when the user releases the device. An application that uses force feedback should disable autocentering before playing effects. +
+
1 - ON: The device should automatically center when the user releases the device. +
+
Not all devices support the autocenter property. +
+
FFPROP_FFGAIN +
Sets the gain for the device. +
+
The pValue member points to a UInt32 that contains a gain value that is applied to all effects created on the device. The value is an integer in the range from 0 through 10,000, specifying the amount by which effect magnitudes should be scaled for the device. For example, a value of 10,000 indicates that all effect magnitudes are to be taken at face value. A value of 9,000 indicates that all effect magnitudes are to be reduced to 90% of their nominal magnitudes. +
+
Setting a gain value is useful when an application wants to scale down the strength of all force-feedback effects uniformly, based on user preferences. + @param pValue Address of the location where the property value is to be read. This function will assume that the data is valid, and of the correct type. + @result If the method succeeds, the return value is FF_OK or FFERR_UNSUPPORTED. +If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
+*/ + HRESULT (*SetProperty)( void * self, FFProperty property, void * pValue ); + + +/*! @function StartEffect + @abstract This function commands the device to play back an effect that was previously loaded. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param downloadID Indicates the effect to be played. + @param mode Specifies how the effect is to affect other effects. Only the mode listed below can be used; all other modes are reserved. For example, the driver never receives the FFES_NODOWNLOAD flag because it is managed by the FF API and not the PlugIn driver. This parameter can be zero, one, or more of the following flags: +
+
FFES_SOLO +
Indicates that all other effects on the device should be stopped before the specified effect is played. If this flag is omitted, the effect is mixed with existing effects that have already started on the device. + @param iterations Specifies the number of times to perform the effect. If the value is FF_INFINITE, then the effect should be repeated until explicitly stopped or paused. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INTERNAL +
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_GENERIC +
FFERR_INVALIDDOWNLOADID +
+*/ + HRESULT (*StartEffect)( void * self, FFEffectDownloadID downloadID, FFEffectStartFlag mode, UInt32 iterations ); + +/*! @function StopEffect + @abstract This function commands the device to stop an effect that was previously started. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param downloadID Indicates the effect to be stopped. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INTERNAL +
FFERR_GENERIC +
FFERR_INVALIDDOWNLOADID +
+*/ + HRESULT (*StopEffect)( void * self, UInt32 downloadID ); +}; + +#endif // #if 0 ¥¥¥ Used for header doc'ing only + +__END_DECLS + +#endif /* ! _IOFORCEFEEDBACKLIB_H */ diff --git a/Frameworks/ForceFeedback.framework/Resources/Info.plist b/Frameworks/ForceFeedback.framework/Resources/Info.plist new file mode 100755 index 0000000..ce08864 --- /dev/null +++ b/Frameworks/ForceFeedback.framework/Resources/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ForceFeedback + CFBundleGetInfoString + 1.0.0, Copyright Apple Computer, Inc. 2002 + CFBundleIdentifier + com.apple.ForceFeedback + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ForceFeedback Framework + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0.0 + + diff --git a/Frameworks/ForceFeedback.framework/Resources/version.plist b/Frameworks/ForceFeedback.framework/Resources/version.plist new file mode 100755 index 0000000..69ea4de --- /dev/null +++ b/Frameworks/ForceFeedback.framework/Resources/version.plist @@ -0,0 +1,18 @@ + + + + + BuildVersion + 70 + CFBundleShortVersionString + 1.0.0 + CFBundleVersion + 1.0.0 + ProjectName + ForceFeedback + ReleaseStatus + Beta + SourceVersion + 1000305 + + diff --git a/Frameworks/ForceFeedback.framework/Versions/A/ForceFeedback b/Frameworks/ForceFeedback.framework/Versions/A/ForceFeedback new file mode 100755 index 0000000000000000000000000000000000000000..b1c427c4cf97cbb0bdb0118121c3365924fe79d3 GIT binary patch literal 19208 zcmeHP4{)2sm4Eu=1`2iA)^gG-_g6(~)C2NZ4`ZivbrqJu?lJ6QOYRQv z{od|=(r3js;ih*pH)9RUzTJJ_dvD*qef#!(&iBc0|MMS-=q42Y%|p4K$a)_24^T|_ z&l(7{Z|Z1AOa1olW1w2KL|u$V5sHO71A$~Xm1Ic%u719FoM=^)h-)(Icp6!C5H#YE z(7;gNwpcVUkR050HI2_Z@aS$Lu8lOvrifGq0-=FqBGUh$>bRQ5`WG;?l}OY%IgIoG zvkoQ#fkt1uPZ2_OSm?kGi098Wu?~3ttV77(6-)*hlE3MnrxK+{18=a)J<~N5?b2IJ z^C}teJkPh9YXc4AGtpo`=`o&6Oh=;(*nZI9+Cam^^AUCt2=rqSu@a>Cr!7dVgf$qWn&~$R}Os$ZEYXc3_b^JX4u%6w<1)WA8JwU@^RC8^hAOE zeM@9pBA6Ij-;@aUg&&P2dI#1w#S)=#Q#jnUEg0%u*R2n%|7tif5Q+564VgL}s5$^SzrR$?3_9 zA)RK8r1?aG>H#s$!GXm3Xk;4~sj78%t%F%dw(%okjmn|(all_9YI4E^E&zrPqE;0C zEmVc=^Hvnpja90C6Ezlh6R*p9qJ}K$+feUD4enl4bh9dU^t%Bwoy91u>$%^Y2L4}Z zAZ;@rzUz4^8s2R_oVHmG4{M=R{o{7ZJbtBp_%X}jbcsc8`|r`L&f)KdQky3y-^xAL zBcH49#WTHEoWl{zVaDU}(Q}g@Wldyzs$z1Cd5l~zANGvES%y~cc4x>7I>$1oUD!Fk zgH+}jv6B|M;$^;|QK6Zr$6Z04EZ0uZxE~!?CNDDG^s_5dOgDXe zZ7SWhH0ADOTDKia4=)`8{c7zwvZDPk(?;7i`Wz9{9Qod_Q%sj>9tADnRONV~UC66o z9^U#p?Ua6QWh%4gvWuMyWEq35#&*64y`3Pc(}+e6{W|5RRWGY~y`lwaOvrJNj(DE8 zlY7_Y8jMGjY)^6D=t*kScK!Q1?gQiiaUnNo`>FC*YK~hy&x7X} z%C6hS(f{(usSi_(2Y6WYpCA+KW#k3Xw<*0{=%y0#wgTtIYRly0h_=K&@}mz~-U|8b zswD<_ZRnp5{k%D{^L^Ia30-gcdK^DFd0MQ;Ua=mX=|`8QG%Hohb)IJh>=N+7qARSg zx)by+@H^ZZeSo?Va^4TUopPV0&RU{3YMu0xS})yLH%8xqPTbI^WAp%d>N?57da3i$ z=xC7qbxvv<^-)V5(XmmiC(m=#MD2cBxrpsSdsOJ^;dG~%vrD^~T%JyiIzwc^VPf%S zic*;`QMKNeS;P4B(hRZ%jk2*^EECJavalR1gXDkf(|P_Y|DgDHg1=4Y<)X<+-wx}Q z0-1`v8S8m%uR*3tqS`g9?N#&dar!dWH#3!F)oJMcezIJeLFR4OE_1~>gUt0Tv-hB> zYX-WZ&p`LFJl$JAP;^UXpxgBs=-zIi`-G%RugpL3dzcA3fL($zj1KsY=KsS@8 zTXBZzVox^~tp5$(jCsoXWA9KEt+x9z=C=Un?5Bzzf8I|f_TAI%qX(~Dt`)yB$hGNH z)~Dw)(A|@#>-_DftWV@K(5*Glefm?@=b>w-yWC*^PGSF8pBD<&XR$Y9YMgn0nyRMT zpT3OAj{e-*>HF4~p(|L^5`90*b*A&^vlsMDps%c;?=|?USJ;Od{AaImzHA#PjkEiz zWrp=%u}Pgrtp)RjT~f=Gc_aFEA!3J)Y9L!~Zo|&6?Hyio|GQ~;Qk>`IkTEwGz&7^L zI7^P;92xr|&JF#nJ$_*F9gasJuPvQgI)roG%jYhi7aPx-_>A4naRh2D{q)KdpRwC6 zYs|mIg+1auNcQ?pje@;o@soKRXUsN1QfdV)4+GGFG&@~|x6@fFPd9h~zi%-M^1TtMx{TsqLdhiReh z!MyBfw}S4oX#2(dh|Xh!gR6&(80Q*dq-(9>~XX1t4E5+Fr62d2dDkpqL9{AI!xJo5_wIrxG{(Dr)QY^G8$J z<%p4rFn`2LnF`vyXCv8$S8hg(N0fPt%Jg`b<1W~BCHU=jKSyPmm14ZgIL>jhjHj0T zV&wZAcaf80##*dF?V8_rX!Efa%gH|a_lQ@1F80Hl!=bO`VyhowFK}$dF*NT9j@k4W z^v*FT8|%VxFYkxYF&WQbP8WEuA%3=JuO~a;uFOX44e-KPIrL1~`DDXG>CVFO~D&2F@#j-gUo$%|i!kg+AVdjk-e&GQ8f(E~EK>39O(k~#slYSvHonI*5&$he${iE;;AHD$@ zOfu#-jX_US`~m28V2`|xy`J|8;K}@WuVR0DMh!lP`TD869yDk63801f{t0}-;-Bk2 zf#;I<35)mfoY)>=BX9k0`U9RX>&8!uoAdtQ=0AQme{k~wu?Fx5kk`R`w$QdPPHBsU z?dnbaZu3LflGuNy$+KxM-Io65(jon9s`J98e2BqeQ`m!J>C<0KjW&VCzLlx;Yim=& z&UTn;u!ep=E&7=8*k_<0e#hik=fK(y<1YFDS?kWg2h^keb*e^jqEw<(`JSY%kzMb@ zZ!EYw{S6T(wqsv7r7aQeV~a9qR~p(6qg`ca2hpxJw7(+nb&Hxuygy@q^pv)gO0vtS zWb`P?tI*Gr;+$~fj%;IJ2))=*TiHjluX5wQg1U_L1)Lfb7m5R=9Hj&_z1laiw=4gF zb=l)SMpo7}bSiQKBR~Ey1wZO=pS4ULg?)|uf!?)$me?2~eEF42|Ok(W}S&CJ@VFLZ^A4}jLS>DD>J(XaO3%@*r z|9eN^Lr=ih{h#hXPh-p~@3mAVebi0=pXD z*PFP{gNAPFub-T}B5ZtSJ$qmeC7dV1nt0hZP&YC!HGfxb{-BF3Fi9+=#i{W9&oi53`)Qo^rMlUOJ@n0gV={8PCVW`w@2L z$*eN$f5?PAP^Co>ue^cv_!j&U{1C61`w;dj{F1&Ga&ls?80dSo$Aq5YPs|p!1MqYq zmdg7W$)lWkC|k(wFQ$1sGdaO?H~6nkzQ;^I|Dsmd2j_VtKg`LuqsW84JU{L`SX9M( zuI>cZ5i;@q&eX&IAYL}eQK{P`a5?YhuH`!r(RbhrIREB>p6^H7;YJQl?Blc4iM9pt z$s1_9mUs!yF(D;4#n47EBRVjUX}x6qp0}~(N@5h@3_o+nSu9^fwvhsviF#; z;3;#Bg}E_71LwiJh`ro(oya`~k#qFojPoJq=tSfY_vE!&z#3@*K5pI6=p7 zZ^M0U;ekBw8$LGhMh@E2S-^X0{tWz>7xQ7AG9Tu_^qIDt+d`j#{(b{}!~+&8pg%Q_ zc1`pb$o$7JuiFjv2Kw-gW{zKtx|^C$yEginy!;E#80b4e-&;U`YF_Qy=vNr%4;$!v zktaJ_K!0j}?3(D8oHWp1W}vTuzE(hgYM$)c=m+!k7aYsehvAdSSwMekzU30^;pOUBI{g$);t8HKH?dyF8`ui1qTipp8 z37g@Sko!+0H-)TXsKH;aRJqqUIbvVf+CX~MR+E!Gxr8Dy%KG8KKmIXswj zhsxLG-XXJ%y&jzWjfnB`K4pyWCF!GU5$Bm+m2snKJoELO?G&?Z`F2=Nxr!{4kVC_r zLcb$Iw?&+9;k!dM`t`da_h(dp4f^#vBlkyCzZ?Df-I4n_m&|m$;=Y1+y_+XL`h&c0 znLkSRF2%Z7yg6S6KL*_LfllGe&T8-F_QNIU+Ntd80^6ppCu#rYkEYoFYUB$s*FTN@ zo1eML{-G=E0f$(}<*>nJ_6_h8h=;5}neVU;=WGnP(q7CR!WPB*dFvv~(TjbT&TIu8 zu@*Q#u&>zeaE}oC0yZ!K-!*l=U&s61T*B+J%C0(l#cO#Hqad&+XZK}NNwOf^iO>0Zm8f_`j!Hj*2%@>$@3{&K!j z$#NciofwyAg9G~$=fglJ&W3{&<^3pq&AERZ@j z?-T0}JnWw`F~{w>eH;~gSLoWjW}wrIy#`<4pc>F>bS;&+A0OV4@cO#{8EcQ+)yRXt zOo_W9@)J0Ji0_>6_vFUAf}_~u#`_}p$uj`YDW4$nU5qDuf}Xd^`-E}f6OgB1S=c9F zp2i%-7|SB>e#l*64S@H!rgBZd^>RKyj+-rzJuYO0Y%D9!LCDJY+x)$@g7-R}74sZG z%z}A#q{ryC_CqT^QFCp@^CIuY&yRfj{ge~u4WFT)pV4?eG%HlNoV7l3{X%c;*_`c!gXrL%*0N0Yyc=kst<54P-f=u4lA zF$aY>f#0GWR^eo4!HFxJ z_$)ZB3a51zoN9$rJqwOq;n-)!dHbTodHdolI1>tIViufng)=@2PFCS$XTgapocJs_ ztqP}g7MyB@Q#}igUE$bg#+kS%aV9R#f-|9TCKv~QOOC$-4}^lzDE}4pU^EI#iiZcT`Wxjsw-9PRJB9Z<*F{@8Z!O$LgYO0@9#?h zpI(TZDPa68zf=8oB5Uz-{Oe!j9WW>B3JDiq0Q?07p9TD93IwiB?X zVB|)uqY|E91^9@BuWJE(O2Uz;zOKqyPsc zyp-{GO86EB;DZt_e+BU0s{UsH|5CyZ{`bsRRR0OA-7TvB6kwNxmpK7@6r2RSMZzmF zUsF`Vt2+QIzH6g^pOpQsR={Hl9s@is;j#(9Ka#NhDZoElKqeFCf&l+cz{m;V)w@-~ zk*$CiNO;A2fXgNP1mrhY2^je#z<0|2L%RU)5-@U1fS;AHhv~c~ z;pR(#Cl-*|#Ca>gA4)ihd08L>_hVXQsRlmD+?3_M1!OUC-V6O5+|RiyzLm^x8dA8(_40DeJ~Zj^qM1WFQk`1kE}C(2Ji2jiADlv6O1NqjoP zh5jC*+gYePP`-dtgMxq4PM=3vhr&3YLs^4@f8$PgQ_Qb==vEYD>BWaAR-uN@X)Vg1 zgpLM6_RVKeH!%Xw zq3UI-UasmDs&=ZHzYhSqmSNP!AH0P46&pLJ!j^BN&Cj!}jL*7d{COz+V|n%e3lMz% zLIGUyx-brZ8-nX;@X<>a3)UH>2xT710xQ&MhAL6)C^w?qgi?x9hO!9dW|YM!@)}VY2Wi5&eRY?vPMJA{t(fUkyeFq2Y$6O%D$Sp_B&Q5EyI|-_`*ED7diQAP4i^Qi8h&lfi9K zL2=7{Ewb;=BgvkoNHi?J4$>M-_V7~}W`k(EFWfDfTbdgsdQ&3SmnXgj{lII$=Twrx z{vc{^iCA@5rrYg)i0Is??QqG2Ga9{xQ2q(h*ym`74Vf??hp~)AG#zMhl zEYTS54h}}Kw0(HR6T`=G`oevo_z;PgI=8Qj5g0s#Eq2#nB-#~D+#SRxXA<{r<1W@5 z5TcR(UT3%~0%H7BS0Ebv#*qHao^6r-E_?+k5N4SJ@mQokDUkwwJ@Um-peGyzVcE;y z=Ltk(vEISBM8-fMV0h&eXoyD#2e_bLa5FqYq3%BU#U`C?PdJLbC25OKITZ{99t^~# zX@Z__Fd1vdSArt_;)^z5(0nfzm=~27adQ~{pfMI6P>bacJ`(1B3cyq&_zF&#UwO5~ Z!=XrbBqTNw+d(YO3l>S_T-8-G|8HW8#+m>C literal 0 HcmV?d00001 diff --git a/Frameworks/ForceFeedback.framework/Versions/A/Headers/ForceFeedback.h b/Frameworks/ForceFeedback.framework/Versions/A/Headers/ForceFeedback.h new file mode 100755 index 0000000..59b8b5d --- /dev/null +++ b/Frameworks/ForceFeedback.framework/Versions/A/Headers/ForceFeedback.h @@ -0,0 +1,816 @@ +//----------------------------------------------------------------------------- +// File: ForceFeedback.h +// Contains: Public interfaces for ForceFeedback technology. +// Copyright: © 2002 by Apple Computer, Inc. All rights reserved. +// +//----------------------------------------------------------------------------- + +#ifndef _FORCEFEEDBACK_H_ +#define _FORCEFEEDBACK_H_ + +#if PRAGMA_ONCE +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! @header ForceFeedback.h + @abstract Public Interfaces to the Force Feedback implementation in Mac OS X. + @discussion The Force Feedback API allows developers to control Force Feedback devices attached to the system. It is a distilled version of the Force Feedback functionality found in Microsoft's DirectInput API. Developers familiar with that API should find this API to be similar. + +*/ + +#include +#if COREFOUNDATION_CFPLUGINCOM_SEPARATE +#include +#endif + +#include +#include +#include + +//----------------------------------------------------------------------------- +// The Version of the FF API +//----------------------------------------------------------------------------- + +enum { + kFFAPIMajorRev = 1, + kFFAPIMinorAndBugRev = 0, + kFFAPIStage = finalStage, + kFFAPINonRelRev = 0 +}; + +//----------------------------------------------------------------------------- +// Effect definition structures +//----------------------------------------------------------------------------- + +struct FFCONSTANTFORCE +{ + LONG lMagnitude; +}; +typedef struct FFCONSTANTFORCE FFCONSTANTFORCE; +typedef FFCONSTANTFORCE * PFFCONSTANTFORCE; + +struct FFRAMPFORCE +{ + LONG lStart; + LONG lEnd; + +}; +typedef struct FFRAMPFORCE FFRAMPFORCE; +typedef FFRAMPFORCE * PFFRAMPFORCE; + +struct FFPERIODIC +{ + DWORD dwMagnitude; + LONG lOffset; + DWORD dwPhase; + DWORD dwPeriod; + +}; +typedef struct FFPERIODIC FFPERIODIC; +typedef FFPERIODIC * PFFPERIODIC; + +struct FFCONDITION +{ + LONG lOffset; + LONG lPositiveCoefficient; + LONG lNegativeCoefficient; + DWORD dwPositiveSaturation; + DWORD dwNegativeSaturation; + LONG lDeadBand; + +}; +typedef struct FFCONDITION FFCONDITION; +typedef FFCONDITION * PFFCONDITION; + +struct FFCUSTOMFORCE +{ + DWORD cChannels; + DWORD dwSamplePeriod; + DWORD cSamples; + LPLONG rglForceData; + +}; +typedef struct FFCUSTOMFORCE FFCUSTOMFORCE; +typedef FFCUSTOMFORCE * PFFCUSTOMFORCE; + +struct FFENVELOPE +{ + DWORD dwSize; /* sizeof(FFENVELOPE) */ + DWORD dwAttackLevel; + DWORD dwAttackTime; /* Microseconds */ + DWORD dwFadeLevel; + DWORD dwFadeTime; /* Microseconds */ + +}; +typedef struct FFENVELOPE FFENVELOPE; +typedef FFENVELOPE * PFFENVELOPE; + +// IMPORTANT NOTE: OBJECT IDS cannot be used to identify trigger buttons +// in FFEFFECT.dwTriggerButton, and output axes in FFEFFECT.rgdwAxes[n]. +// Please use object offsets (FFJOFS_* constants), the only supported method. +struct FFEFFECT +{ + DWORD dwSize; /* sizeof(FFEFFECT) */ + DWORD dwFlags; /* FFEFF_* */ + DWORD dwDuration; /* Microseconds */ + DWORD dwSamplePeriod; /* Microseconds */ + DWORD dwGain; + DWORD dwTriggerButton; /* or FFEB_NOTRIGGER */ + DWORD dwTriggerRepeatInterval; /* Microseconds */ + DWORD cAxes; /* Number of axes */ + LPDWORD rgdwAxes; /* Array of axes */ + LPLONG rglDirection; /* Array of directions */ + PFFENVELOPE lpEnvelope; /* Optional */ + DWORD cbTypeSpecificParams; /* Size of params */ + void* lpvTypeSpecificParams; /* Pointer to params */ + DWORD dwStartDelay; /* Microseconds */ + +}; +typedef struct FFEFFECT FFEFFECT; +typedef FFEFFECT * PFFEFFECT; + +struct FFEFFESCAPE +{ + DWORD dwSize; + DWORD dwCommand; + void* lpvInBuffer; + DWORD cbInBuffer; + void* lpvOutBuffer; + DWORD cbOutBuffer; + +}; +typedef struct FFEFFESCAPE FFEFFESCAPE; +typedef FFEFFESCAPE * PFFEFFESCAPE; + +// NOTE: this structure has no DirectInput equivalent +struct FFCAPABILITIES +{ + NumVersion ffSpecVer; // Version of specification supported by the driver + UInt32 supportedEffects; // FFCAP_ET_*; including emulated effects + UInt32 emulatedEffects; // FFCAP_ET_*; driver-emulated effects + UInt32 subType; // FFCAP_TYPE_* + UInt32 numFfAxes; + UInt8 ffAxes[32]; + UInt32 storageCapacity; // number of effects that can be stored + // by the driver/device + UInt32 playbackCapacity; // number of effects that can be _simultaneously_ + // played back by the driver/device + NumVersion firmwareVer; // device firmware version, vendor-defined + NumVersion hardwareVer; // hardware version, vendor-defined + NumVersion driverVer; // driver version, vendor-defined + +}; +typedef struct FFCAPABILITIES FFCAPABILITIES; +typedef FFCAPABILITIES * PFFCAPABILITIES; + + + +//----------------------------------------------------------------------------- +// Object reference pointers +//----------------------------------------------------------------------------- + +// FFDeviceObjectReference and FFEffectObjectReference are opaque handles +// to objects created and maintained by the FF API. +// A FFDeviceObjectReference is obtained through a call to FFCreateDevice and +// refers to a specific attached device supporting force feedback. This +// reference may be passed to any of the "FFDevice" functions (below). When +// you are through with it, call FFReleaseDevice to release the memory. +// Similarly, a FFEffectObjectReference is obtained through a call to +// FFDeviceCreateEffect and refers to a created force feedback effect on a +// particular device. This reference may be passed to any of the "FFEffect" +// functions. Call FFDeviceReleaseEffect to unload the effect and clean up +// its memory. - Jeff Mallett 9/25/02 +// +typedef struct {} __FFDHIDDEN, * FFDeviceObjectReference; +typedef struct {} __FFEHIDDEN, * FFEffectObjectReference; + + +//----------------------------------------------------------------------------- +// FF (general) function prototypes +//----------------------------------------------------------------------------- + +/*! @function FFCreateDevice + @abstract Creates a new API device object from an OS object in preparation to use the device for force feedback. + @param hidDevice Pointer to a HID device object. + @param pdeviceReference Address of a variable to receive an opaque reference handle to a new device object. This reference can be used in subsequent calls to FFDevice* functions + @result If the method succeeds, and the device supports FF, the return value is FF_OK. +If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOINTERFACE +
FFERR_OUTOFMEMORY +
FFERR_INTERNAL +
+ @discussion When you are finished with the device, FFReleaseDevice must be called on the reference received in this function to dispose of the API device object. +*/ + +extern HRESULT +FFCreateDevice( + io_service_t hidDevice, + FFDeviceObjectReference * pDeviceReference + ); + + +/*! @function FFReleaseDevice + @abstract Disposes of an API device object created with FFCreateDevice. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @result If the method succeeds, and the device supports FF, the return value is FF_OK. +If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOINTERFACE +
FFERR_OUTOFMEMORY +
+ @discussion +*/ + +extern HRESULT +FFReleaseDevice( + FFDeviceObjectReference deviceReference + ); + + +/*! @function FFIsForceFeedback + @abstract Used to determine if a particular device provided by HID Manager is a force feedback device. + @param hidDevice Pointer to a HID device object to be tested for force feedback support. + @result If the method succeeds, and the device supports FF, the return value is FF_OK. If the method succeeds, and the device does not support FF, the return value is FFERR_NOINTERFACE. If the method fails, the return value is FFERR_INVALIDPARAM + @discussion When you are finished with the device, FFReleaseDevice must be called on the reference received in this function to dispose of the API device object. +*/ + +extern HRESULT +FFIsForceFeedback( + io_service_t hidDevice + ); + + +//----------------------------------------------------------------------------- +// FFDevice (device related) function prototypes +//----------------------------------------------------------------------------- + +/*! @function FFDeviceCreateEffect + @abstract Creates and initializes an instance of an effect identified by the effect UUID on the device. + @param deviceReference An opaque reference handle to a device object. This is obtained from a previous call to FFCreateDevice. + @param uuidRef Reference to the UUID identifying the effect to be created. Only predefined effect UUIDs are accepted. The following standard effect UUIDs are defined: +
+
kFFEffectType_ConstantForce_ID +
kFFEffectType_RampForce_ID +
kFFEffectType_Square_ID +
kFFEffectType_Sine_ID +
kFFEffectType_Triangle_ID +
kFFEffectType_SawtoothUp_ID +
kFFEffectType_SawtoothDown_ID +
kFFEffectType_Spring_ID +
kFFEffectType_Damper_ID +
kFFEffectType_Inertia_ID +
kFFEffectType_Friction_ID +
kFFEffectType_CustomForce_ID +
+
+ @param pEffectDefinition Pointer to FFEFFECT structure that provides parameters for the created effect. This parameter is optional. If it is NULL, the effect object is created without parameters. The application must then call the FFEffectSetParameters function to set the parameters of the effect before it can download the effect. + @param pEffectReference Address of a variable to receive an opaque reference handle to a new effect object. This reference can be used in subsequent calls to FFEffect* functions. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_UNSUPPORTEDAXIS +
FFERR_OUTOFMEMORY +
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_INVALIDDOWNLOADID +
FFERR_INTERNAL +
FFERR_EFFECTTYPEMISMATCH +
+ @discussion When you are finished with the effect, FFReleaseEffect must be called on the reference received in this function to dispose of the API effect object. +*/ + +extern HRESULT +FFDeviceCreateEffect( + FFDeviceObjectReference deviceReference, + CFUUIDRef uuidRef, + FFEFFECT * pEffectDefinition, + FFEffectObjectReference * pEffectReference + ); + + +/*! @function FFDeviceReleaseEffect + @abstract Disposes of an API effect object created with FFDeviceCreateEffect. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @param effectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
FFERR_GENERIC +
FFERR_INTERNAL +
FFERR_INVALIDDOWNLOADID +
+ @discussion +*/ + +extern HRESULT +FFDeviceReleaseEffect( + FFDeviceObjectReference deviceReference, + FFEffectObjectReference effectReference + ); + +/*! @function FFDeviceEscape + @abstract Sends a hardware-specific command to the device. + @param deviceReference An opaque reference handle to a device object. This is obtained from a previous call to FFCreateDevice. + @param pFFEffectEscape Pointer to FFEFFESCAPE structure that describes the command to be sent. On success, the cbOutBuffer member contains the number of bytes of the output buffer used. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_UNSUPPORTED +
+ @discussion Because each driver implements different escapes, it is the application's responsibility to ensure that it is sending the escape to the correct driver. +*/ +extern HRESULT +FFDeviceEscape( + FFDeviceObjectReference deviceReference, + FFEFFESCAPE * pFFEffectEscape + ); + +/*! @function FFDeviceGetForceFeedbackState + @abstract Retrieves the state of the device's force feedback system. + @param deviceReference An opaque reference handle to a device object. This is obtained from a previous call to FFCreateDevice. + @param pFFState Location for flags that describe the current state of the device's force feedback system. +The value is a combination of the following constants: +
+
FFGFFS_ACTUATORSOFF +
The device's force feedback actuators are disabled. +
+
FFGFFS_ACTUATORSON +
The device's force feedback actuators are enabled. +
+
FFGFFS_DEVICELOST +
The device suffered an unexpected failure and is in an indeterminate state. It must be reset either by unacquiring and reacquiring the device, or by sending a FFSFFC_RESET command. +
+
FFGFFS_EMPTY +
The device has no downloaded effects. +
+
FFGFFS_PAUSED +
Playback of all active effects has been paused. +
+
FFGFFS_POWEROFF +
The force feedback system is not currently available. If the device cannot report the power state, neither FFGFFS_POWERON nor FFGFFS_POWEROFF is returned. +
+
FFGFFS_POWERON +
Power to the force feedback system is currently available. If the device cannot report the power state, neither FFGFFS_POWERON nor FFGFFS_POWEROFF is returned. +
+
FFGFFS_SAFETYSWITCHOFF +
The safety switch is currently off; that is, the device cannot operate. If the device cannot report the state of the safety switch, neither FFGFFS_SAFETYSWITCHON nor FFGFFS_SAFETYSWITCHOFF is returned. +
+
FFGFFS_SAFETYSWITCHON +
The safety switch is currently on; that is, the device can operate. If the device cannot report the state of the safety switch, neither FFGFFS_SAFETYSWITCHON nor FFGFFS_SAFETYSWITCHOFF is returned. +
+
FFGFFS_STOPPED +
No effects are playing, and the device is not paused. +
+
FFGFFS_USERFFSWITCHOFF +
The user force feedback switch is currently off; that is, the device cannot operate. If the device cannot report the state of the user force feedback switch, neither FFGFFS_USERFFSWITCHON nor FFGFFS_USERFFSWITCHOFF is returned. +
+
FFGFFS_USERFFSWITCHON +
The user force feedback switch is currently on; that is, the device can operate. If the device cannot report the state of the user force feedback switch, neither FFGFFS_USERFFSWITCHON nor FFGFFS_USERFFSWITCHOFF is returned. +
+
Future versions can define additional flags. Applications should ignore any flags that are not currently defined. +
+ @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
+ @discussion +*/ + +extern HRESULT +FFDeviceGetForceFeedbackState( + FFDeviceObjectReference deviceReference, + FFState * pFFState + ); + +/*! @function FFDeviceSendForceFeedbackCommand + @abstract Sends a command to the device's force feedback system. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @param flags Single value indicating the desired change in state. The value can be one of the following: +
+
FFSFFC_CONTINUE +
Paused playback of all active effects is to be continued. It is an error to send this command when the device is not in a paused state. +
+
FFSFFC_PAUSE +
Playback of all active effects is to be paused. This command also stops the clock-on effects so that they continue playing to their full duration when restarted. +
+
While the device is paused, new effects cannot be started, and existing ones cannot be modified. Doing so can cause the subsequent FFSFFC_CONTINUE command to fail to perform properly. +
+
To abandon a pause and stop all effects, use the FFSFFC_STOPALL or FFSFCC_RESET commands. +
+
FFSFFC_RESET +
The device's force feedback system is to be put in its startup state. All effects are removed from the device, are no longer valid, and must be recreated if they are to be used again. The device's actuators are disabled. +
+
FFSFFC_SETACTUATORSOFF +
The device's force feedback actuators are to be disabled. While the actuators are off, effects continue to play but are ignored by the device. Using the analogy of a sound playback device, they are muted, rather than paused. +
+
FFSFFC_SETACTUATORSON +
The device's force feedback actuators are to be enabled. +
+
FFSFFC_STOPALL +
Playback of any active effects is to be stopped. All active effects are reset, but are still being maintained by the device and are still valid. If the device is in a paused state, that state is lost. +
+
This command is equivalent to calling the FFEffect_Stop method for each effect playing. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_INTERNAL +
+ @discussion +*/ + +extern HRESULT +FFDeviceSendForceFeedbackCommand( + FFDeviceObjectReference deviceReference, + FFCommandFlag flags + ); + +/*! @function FFDeviceSetForceFeedbackProperty + @abstract Retrieves the device's force feedback capabilities. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @param property The following property values are defined for a FF device: +
+
FFPROP_AUTOCENTER +
Specifies whether the actuated FF axes are self-centering. This property controls the device's "default centering spring". +
The pValue member points to a UInt32 can be one of the following values. +
0 - OFF: The device should not automatically center when the user releases the device. An application that uses force feedback should disable autocentering before playing effects. +
1 - ON: The device should automatically center when the user releases the device. +
Not all devices support the autocenter property. +
+
FFPROP_FFGAIN +
Sets the gain for the device. +
The pValue member points to a UInt32 that contains a gain value that is applied to all effects created on the device. The value is an integer in the range from 0 through 10,000, specifying the amount by which effect magnitudes should be scaled for the device. For example, a value of 10,000 indicates that all effect magnitudes are to be taken at face value. A value of 9,000 indicates that all effect magnitudes are to be reduced to 90% of their nominal magnitudes. +
Setting a gain value is useful when an application wants to scale down the strength of all force feedback effects uniformly, based on user preferences. + @param pValue Address of the location where the property value is to be read. SetForceFeedbackProperty will assume that the data is valid, and of the correct type. + @result If the method succeeds, the return value is FF_OK or FFERR_UNSUPPORTED. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
+ @discussion +*/ + +extern HRESULT +FFDeviceSetForceFeedbackProperty( + FFDeviceObjectReference deviceReference, + FFProperty property, + void * pValue + ); + +/*! @function FFDeviceGetForceFeedbackProperty + @abstract Gets properties that define the device behavior. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @param property The following property values are defined for a FF device (see FFDeviceSetForceFeedbackProperty for details): +
+
FFPROP_AUTOCENTER +
FFPROP_FFGAIN +
+ @param pValue Address of the location where the value associated with the property is to be stored. GetForceFeedbackProperty assumes that the pointer is valid, although it will perform a size check before writing the data to pValue + @param valueSize Size, in bytes, of data area pointed to by pValue. Size is compared to expected property size, and the function fails if a mismatch occurs. + @result If the method succeeds, the return value is FF_OK or FFERR_UNSUPPORTED. +If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
+ @discussion +*/ +extern HRESULT +FFDeviceGetForceFeedbackProperty( + FFDeviceObjectReference deviceReference, + FFProperty property, + void * pValue, + IOByteCount valueSize + ); + +/*! @function FFDeviceSetCooperativeLevel + @abstract Function is unimplemented in version 1.0 of this API + @discussion +*/ +extern HRESULT +FFDeviceSetCooperativeLevel( + FFDeviceObjectReference deviceReference, + void * taskIdentifier, + FFCooperativeLevelFlag flags + ); + +/*! @function FFDeviceGetForceFeedbackCapabilities + @abstract Retrieves the device's force feedback capabilities. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @param pFFCapabilities Pointer to a FFCAPABILITIES structure that is to be filled in by the this call. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
+ @discussion +*/ + +extern HRESULT +FFDeviceGetForceFeedbackCapabilities( + FFDeviceObjectReference deviceReference, + FFCAPABILITIES * pFFCapabilities + ); + + +//----------------------------------------------------------------------------- +// FFEffect (effect related) function prototypes +//----------------------------------------------------------------------------- + +/*! @function FFEffectDownload + @abstract Places the effect on the device. If the effect is already on the device, the existing effect is updated to match the values set by the FFEffectSetParameters method. + @param efffectRef An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @result If the method succeeds, the return value is FF_OK or S_FALSE. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_INVALIDDOWNLOADID +
FFERR_INTERNAL +
FFERR_EFFECTTYPEMISMATCH +
+
If the method returns S_FALSE, the effect has already been downloaded to the device. +
+ @discussion It is valid to update an effect while it is playing. The semantics of such an operation are explained in the reference for FFEffectSetParameters. +*/ + +extern HRESULT +FFEffectDownload( + FFEffectObjectReference effectReference + ); + +/*! @function FFEffectEscape + @abstract Sends a hardware-specific command to the driver. + @param effectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @param pFFEffectEscape FFEFFESCAPE structure that describes the command to be sent. On success, the cbOutBuffer member contains the number of bytes of the output buffer used. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
FFERR_UNSUPPORTED +
+
Other device-specific error codes are also possible. Ask the hardware manufacturer for details +
+ @discussion Because each driver implements different escapes, it is the application's responsibility to ensure that it is sending the escape to the correct driver. +*/ + +extern HRESULT +FFEffectEscape( + FFEffectObjectReference effectReference, + FFEFFESCAPE * pFFEffectEscape + ); + +/*! @function FFEffectGetEffectStatus + @abstract Sends a hardware-specific command to the driver. + @param effectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @param pFlags Pointer to status flags for the effect. The value can be 0 or one or more of the following constants: +
+
FFEGES_PLAYING +
The effect is playing. +
+
FFEGES_EMULATED +
The effect is emulated. +
+ @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
+ @discussion +*/ + +extern HRESULT +FFEffectGetEffectStatus( + FFEffectObjectReference effectReference, + FFEffectStatusFlag * pFlags + ); + +/*! @function FFEffectGetParameters + @abstract Retrieves information about an effect. + @param efffectRef An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @param pFFEffect Address of a FFEFFECT structure that receives effect information. The dwSize member must be filled in by the application before calling this method. + @param flags Flags that specify which parts of the effect information are to be retrieved. The value can be 0 or one or more of the following constants: +
+
FFEP_ALLPARAMS +
The union of all other FFEP_* flags, indicating that all members of the FFEFFECT structure are being requested. +
+
FFEP_AXES +
The cAxes and rgdwAxes members should receive data. The cAxes member on entry contains the size (in DWORDs) of the buffer pointed to by the rgdwAxes member. If the buffer is too small, the method returns FFERR_MOREDATA and sets cAxes to the necessary size of the buffer. +
+
FFEP_DIRECTION +
The cAxes and rglDirection members should receive data. The cAxes member on entry contains the size (in DWORDs) of the buffer pointed to by the rglDirection member. If the buffer is too small, the GetParameters method returns FFERR_MOREDATA and sets cAxes to the necessary size of the buffer. +
The dwFlags member must include at least one of the coordinate system flags (FFEFF_CARTESIAN, FFEFF_POLAR, or FFEFF_SPHERICAL). The API returns the direction of the effect in one of the coordinate systems you specified, converting between coordinate systems as necessary. On exit, exactly one of the coordinate system flags is set in the dwFlags member, indicating which coordinate system the FF API used. In particular, passing all three coordinate system flags retrieves the coordinates in exactly the same format in which they were set. +
+
FFEP_DURATION +
The dwDuration member should receive data. +
+
FFEP_ENVELOPE +
The lpEnvelope member points to a FFENVELOPE structure that should receive data. If the effect does not have an envelope associated with it, the lpEnvelope member is set to NULL. +
+
FFEP_GAIN +
The dwGain member should receive data. +
+
FFEP_SAMPLEPERIOD +
The dwSamplePeriod member should receive data. +
+
FFEP_STARTDELAY +
The dwStartDelay member should receive data. +
+
FFEP_TRIGGERBUTTON +
The dwTriggerButton member should receive data. +
+
FFEP_TRIGGERREPEATINTERVAL +
The dwTriggerRepeatInterval member should receive data. +
+
FFEP_TYPESPECIFICPARAMS +
The lpvTypeSpecificParams member points to a buffer whose size is specified by the cbTypeSpecificParams member. On return, the buffer is filled in with the type-specific data associated with the effect, and the cbTypeSpecificParams member contains the number of bytes copied. If the buffer supplied by the application is too small to contain all the type-specific data, the method returns FFERR_MOREDATA, and the cbTypeSpecificParams member contains the required size of the buffer in bytes. +
+ @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
FFERR_MOREDATA +
+ @discussion Common errors resulting in a FFERR_INVALIDPARAM error include not setting the dwSize member of the FFEFFECT structure, passing invalid flags, or not setting up the members in the FFEFFECT structure properly in preparation for receiving the effect information. +*/ + +extern HRESULT +FFEffectGetParameters( + FFEffectObjectReference effectReference, + FFEFFECT * pFFEffect, + FFEffectParameterFlag flags + ); + +/*! @function FFEffectSetParameters + @abstract Sets the characteristics of an effect. + @param efffectRef An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @param pFFEffect Address of a FFEFFECT structure that contains effect information. The dwSize member must be filled in by the application before calling this method, as well as any members specified by corresponding bits in the flags parameter. + @param flags Flags that specify which portions of the effect information are to be set and how the downloading of the parameters should be handled. The value can be 0 or one or more of the following constants: +
+
FFEP_AXES +
The cAxes and rgdwAxes members contain data. +
+
FFEP_DIRECTION +
The cAxes and rglDirection members contain data. The dwFlags member specifies (with FFEFF_CARTESIAN or FFEFF_POLAR) the coordinate system in which the values should be interpreted. +
+
FFEP_DURATION +
The dwDuration member contains data. +
+
FFEP_ENVELOPE +
The lpEnvelope member points to a FFENVELOPE structure that contains data. To detach any existing envelope from the effect, pass this flag and set the lpEnvelope member to NULL. +
+
FFEP_GAIN +
The dwGain member contains data. +
+
FFEP_NODOWNLOAD +
Suppress the automatic FFEffect_Download that is normally performed after the parameters are updated. +
+
FFEP_NORESTART +
Suppress the stopping and restarting of the effect to change parameters. See Remarks. +
+
FFEP_SAMPLEPERIOD +
The dwSamplePeriod member contains data. +
+
FFEP_START +
The effect is to be started (or restarted if it is currently playing) after the parameters are updated. By default, the play state of the effect is not altered. +
+
FFEP_STARTDELAY +
The dwStartDelay member contains data. +
+
FFEP_TRIGGERBUTTON +
The dwTriggerButton member contains data. +
+
+
The dwTriggerRepeatInterval member contains data. +
+
FFEP_TYPESPECIFICPARAMS +
The lpvTypeSpecificParams and cbTypeSpecificParams members of the FFEFFECT structure contain the address and size of type-specific data for the effect. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_UNSUPPORTEDAXIS +
FFERR_OUTOFMEMORY +
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_INVALIDDOWNLOADID +
FFERR_INTERNAL +
FFERR_EFFECTTYPEMISMATCH +
+ @discussion The FFEffectSetParameters method automatically downloads the effect, but this behavior can be suppressed by setting the FFEP_NODOWNLOAD flag. If automatic download has been suppressed, you can manually download the effect by invoking the FFEffectDownload method. +
+
If the effect is playing while the parameters are changed, the new parameters take effect as if they were the parameters when the effect started. +
+
For example, suppose a periodic effect with a duration of three seconds is started. After two seconds, the direction of the effect is changed. The effect then continues for one additional second in the new direction. The envelope, phase, amplitude, and other parameters of the effect continue smoothly, as if the direction had not changed. +
+
In the same situation, if after two seconds the duration of the effect were changed to 1.5 seconds, the effect would stop. +
+
Normally, if the driver cannot update the parameters of a playing effect, the driver is permitted to stop the effect, update the parameters, and then restart the effect. Passing the FFEP_NORESTART flag suppresses this behavior. If the driver cannot update the parameters of an effect while it is playing, the error code FFERR_EFFECTPLAYING is returned, and the parameters are not updated. +
+
No more than one of the FFEP_NODOWNLOAD, FFEP_START, and FFEP_NORESTART flags should be set. (It is also valid to pass none of them.) +
+
These three flags control download and playback behavior as follows: +
+
If FFEP_NODOWNLOAD is set, the effect parameters are updated but not downloaded to the device. +
+
If the FFEP_START flag is set, the effect parameters are updated and downloaded to the device, and the effect is started just as if the FFEffect_Start method had been called with the dwIterations parameter set to 1 and with no flags. (Combining the update with FFEP_START is slightly faster than calling Start separately, because it requires less information to be transmitted to the device.) +
+
If neither FFEP_NODOWNLOAD nor FFEP_START is set and the effect is not playing, the parameters are updated and downloaded to the device. +
+
If neither FFEP_NODOWNLOAD nor FFEP_START is set and the effect is playing, the parameters are updated if the device supports on-the-fly updating. Otherwise the behavior depends on the state of the FFEP_NORESTART flag. If it is set, the error code FFERR_EFFECTPLAYING is returned. If it is clear, the effect is stopped, the parameters are updated, and the effect is restarted. + +*/ + +extern HRESULT +FFEffectSetParameters( + FFEffectObjectReference effectReference, + FFEFFECT * pFFEffect, + FFEffectParameterFlag flags + ); + +/*! @function FFEffectStart + @abstract Begins playing an effect. If the effect is already playing, it is restarted from the beginning. If the effect has not been downloaded or has been modified since its last download, it is downloaded before being started. This default behavior can be suppressed by passing the FFES_NODOWNLOAD flag. + @param efffectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @param iterations Number of times to play the effect in sequence. The envelope is re-articulated with each iteration. +
+
To play the effect exactly once, pass 1. To play the effect repeatedly until explicitly stopped, pass INFINITE. To play the effect until explicitly stopped without re-articulating the envelope, modify the effect parameters with the FFEffect_SetParameters method, and change the dwDuration member to INFINITE. + @param flags Flags that describe how the effect should be played by the device. The value can be 0 or one or more of the following values: +
+
FFES_SOLO +
All other effects on the device should be stopped before the specified effect is played. If this flag is omitted, the effect is mixed with existing effects already started on the device. +
+
FFES_NODOWNLOAD +
Do not automatically download the effect. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_INVALIDDOWNLOADID +
FFERR_INTERNAL +
FFERR_EFFECTTYPEMISMATCH +
FFERR_GENERIC +
+ @discussion Not all devices support multiple iterations. +*/ + +extern HRESULT +FFEffectStart( + FFEffectObjectReference effectReference, + UInt32 iterations, + FFEffectStartFlag flags + ); + +/*! @function FFEffectStop + @abstract Stops playing an effect. + @param effectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
FFERR_GENERIC +
FFERR_INTERNAL +
FFERR_INVALIDDOWNLOADID +
+ @discussion +*/ + +extern HRESULT +FFEffectStop( + FFEffectObjectReference effectReference + ); + +/*! @function FFEffectUnload + @abstract Removes the effect from the device. If the effect is playing, it is automatically stopped before it is unloaded. + @param effectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
FFERR_GENERIC +
FFERR_INTERNAL +
FFERR_INVALIDDOWNLOADID +
+ @discussion +*/ +extern HRESULT +FFEffectUnload( + FFEffectObjectReference effectReference + ); + + +#ifdef __cplusplus +} +#endif + +#endif // _FORCEFEEDBACK_H_ + + + + + + + diff --git a/Frameworks/ForceFeedback.framework/Versions/A/Headers/ForceFeedbackConstants.h b/Frameworks/ForceFeedback.framework/Versions/A/Headers/ForceFeedbackConstants.h new file mode 100755 index 0000000..30e5222 --- /dev/null +++ b/Frameworks/ForceFeedback.framework/Versions/A/Headers/ForceFeedbackConstants.h @@ -0,0 +1,572 @@ +//----------------------------------------------------------------------------- +// File: ForceFeedbackConstants.h +// Contains: Public interfaces for ForceFeedback technology. +// Copyright: © 2002 by Apple Computer, Inc. All rights reserved. +// +//----------------------------------------------------------------------------- + +#ifndef _FORCEFEEDBACKCONSTANTS_H_ +#define _FORCEFEEDBACKCONSTANTS_H_ + +#if PRAGMA_ONCE +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! @header ForceFeedbackConstants.h + @abstract Constants used in the public interfaces to the Force Feedback implementation in Mac OS X. + @discussion This header file contains the Effect type UUIDs, type definitions used in the API, force feedback + constants and error values used by the API. + +*/ + +//----------------------------------------------------------------------------- +// General defines +//----------------------------------------------------------------------------- +#if !defined( DWORD ) +typedef UInt32 DWORD; +typedef DWORD* LPDWORD; +#endif +#if !defined( LONG ) +typedef SInt32 LONG; +typedef LONG* LPLONG; +#endif + +#define FF_INFINITE 0xFFFFFFFF + +#define FF_DEGREES 100 +#define FF_FFNOMINALMAX 10000 +#define FF_SECONDS 1000000 + + +//----------------------------------------------------------------------------- +// Effect type UUIDs +//----------------------------------------------------------------------------- + +// E559C460-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_ConstantForce_ID + @discussion UUID for a constant force effect type + */ +#define kFFEffectType_ConstantForce_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x60, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C461-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_RampForce_ID + @discussion UUID for a ramp force effect type + */ +#define kFFEffectType_RampForce_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x61, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C462-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Square_ID + @discussion UUID for a square wave effect type + */ +#define kFFEffectType_Square_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x62, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C463-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Sine_ID + @discussion UUID for a sine wave effect type + */ +#define kFFEffectType_Sine_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x63, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C464-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Sine_ID + @discussion UUID for a sine wave effect type + */ +#define kFFEffectType_Triangle_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x64, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C465-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_SawtoothUp_ID + @discussion UUID for a upwards sawtooth wave effect type + */ +#define kFFEffectType_SawtoothUp_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x65, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C466-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_SawtoothDown_ID + @discussion UUID for a downwards sawtooth wave effect type + */ +#define kFFEffectType_SawtoothDown_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x66, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C467-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Spring_ID + @discussion UUID for a spring effect type + */ +#define kFFEffectType_Spring_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x67, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C468-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Damper_ID + @discussion UUID for a damper effect type + */ +#define kFFEffectType_Damper_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x68, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C469-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Inertia_ID + @discussion UUID for an inertia effect type + */ +#define kFFEffectType_Inertia_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x69, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C46A-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Friction_ID + @discussion UUID for a friction effect type + */ +#define kFFEffectType_Friction_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x6A, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C46B-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_CustomForce_ID + @discussion UUID for a custom force effect type + */ +#define kFFEffectType_CustomForce_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x6B, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +//----------------------------------------------------------------------------- +// Effect definition constants +//----------------------------------------------------------------------------- + +// FFEFFECT.dwFlags constants +// IMPORTANT NOTE: OBJECT IDS cannot be used to identify trigger buttons +// in FFEFFECT.dwTriggerButton, and output axes in FFEFFECT.rgdwAxes[n]. +// Please use object offsets (FFJOFS_* constants), the only supported method. +// #define FFEFF_OBJECTIDS 0x00000001 +#define FFEFF_OBJECTOFFSETS 0x00000002 + +typedef UInt32 FFCoordinateSystemFlag; +enum +{ + FFEFF_CARTESIAN = 0x00000010, + FFEFF_POLAR = 0x00000020, + FFEFF_SPHERICAL = 0x00000040 +}; + +// Effect Parameter flags for use in calls to FFEffectGetParameters() and FFEffectSetParameters() +// +typedef UInt32 FFEffectParameterFlag; +enum +{ + FFEP_DURATION = 0x00000001, + FFEP_SAMPLEPERIOD = 0x00000002, + FFEP_GAIN = 0x00000004, + FFEP_TRIGGERBUTTON = 0x00000008, + FFEP_TRIGGERREPEATINTERVAL = 0x00000010, + FFEP_AXES = 0x00000020, + FFEP_DIRECTION = 0x00000040, + FFEP_ENVELOPE = 0x00000080, + FFEP_TYPESPECIFICPARAMS = 0x00000100, + FFEP_STARTDELAY = 0x00000200, + FFEP_ALLPARAMS = 0x000003FF, + FFEP_START = 0x20000000, + FFEP_NORESTART = 0x40000000, + FFEP_NODOWNLOAD = 0x80000000, + FFEB_NOTRIGGER = 0xFFFFFFFF +}; + +// Effect Parameter flags for use in calls to FFEffectStart() +// +typedef UInt32 FFEffectStartFlag; +enum +{ + FFES_SOLO = 0x00000001, + FFES_NODOWNLOAD = 0x80000000 +}; + +// Effect Parameter flags for use in calls to FFEffectGetEffectStatus() +// +typedef UInt32 FFEffectStatusFlag; +enum +{ + FFEGES_NOTPLAYING = 0x00000000, + FFEGES_PLAYING = 0x00000001, + FFEGES_EMULATED = 0x00000002 +}; + +// command flags for FFDeviceSendForceFeedbackCommand() +// +typedef UInt32 FFCommandFlag; +enum +{ + FFSFFC_RESET = 0x00000001, + FFSFFC_STOPALL = 0x00000002, + FFSFFC_PAUSE = 0x00000004, + FFSFFC_CONTINUE = 0x00000008, + FFSFFC_SETACTUATORSON = 0x00000010, + FFSFFC_SETACTUATORSOFF = 0x00000020 +}; + +// device state flags returned by FFDeviceGetForceFeedbackState() +// +typedef UInt32 FFState; +enum +{ + FFGFFS_EMPTY = 0x00000001, + FFGFFS_STOPPED = 0x00000002, + FFGFFS_PAUSED = 0x00000004, + FFGFFS_ACTUATORSON = 0x00000010, + FFGFFS_ACTUATORSOFF = 0x00000020, + FFGFFS_POWERON = 0x00000040, + FFGFFS_POWEROFF = 0x00000080, + FFGFFS_SAFETYSWITCHON = 0x00000100, + FFGFFS_SAFETYSWITCHOFF = 0x00000200, + FFGFFS_USERFFSWITCHON = 0x00000400, + FFGFFS_USERFFSWITCHOFF = 0x00000800, + FFGFFS_DEVICELOST = 0x80000000 +}; + + +// axis and button "field offsets", +// used in +// FFEFFECT.dwTriggerButton +// FFEFFECT.rgdwAxes[n] +#define FFJOFS_X 0 +#define FFJOFS_Y 4 +#define FFJOFS_Z 8 +#define FFJOFS_RX 12 +#define FFJOFS_RY 16 +#define FFJOFS_RZ 20 +#define FFJOFS_SLIDER(n) (24 + (n) * sizeof(LONG)) +#define FFJOFS_POV(n) (32 + (n) * sizeof(DWORD)) +#define FFJOFS_BUTTON(n) (48 + (n)) +#define FFJOFS_BUTTON0 FFJOFS_BUTTON(0) +#define FFJOFS_BUTTON1 FFJOFS_BUTTON(1) +#define FFJOFS_BUTTON2 FFJOFS_BUTTON(2) +#define FFJOFS_BUTTON3 FFJOFS_BUTTON(3) +#define FFJOFS_BUTTON4 FFJOFS_BUTTON(4) +#define FFJOFS_BUTTON5 FFJOFS_BUTTON(5) +#define FFJOFS_BUTTON6 FFJOFS_BUTTON(6) +#define FFJOFS_BUTTON7 FFJOFS_BUTTON(7) +#define FFJOFS_BUTTON8 FFJOFS_BUTTON(8) +#define FFJOFS_BUTTON9 FFJOFS_BUTTON(9) +#define FFJOFS_BUTTON10 FFJOFS_BUTTON(10) +#define FFJOFS_BUTTON11 FFJOFS_BUTTON(11) +#define FFJOFS_BUTTON12 FFJOFS_BUTTON(12) +#define FFJOFS_BUTTON13 FFJOFS_BUTTON(13) +#define FFJOFS_BUTTON14 FFJOFS_BUTTON(14) +#define FFJOFS_BUTTON15 FFJOFS_BUTTON(15) +#define FFJOFS_BUTTON16 FFJOFS_BUTTON(16) +#define FFJOFS_BUTTON17 FFJOFS_BUTTON(17) +#define FFJOFS_BUTTON18 FFJOFS_BUTTON(18) +#define FFJOFS_BUTTON19 FFJOFS_BUTTON(19) +#define FFJOFS_BUTTON20 FFJOFS_BUTTON(20) +#define FFJOFS_BUTTON21 FFJOFS_BUTTON(21) +#define FFJOFS_BUTTON22 FFJOFS_BUTTON(22) +#define FFJOFS_BUTTON23 FFJOFS_BUTTON(23) +#define FFJOFS_BUTTON24 FFJOFS_BUTTON(24) +#define FFJOFS_BUTTON25 FFJOFS_BUTTON(25) +#define FFJOFS_BUTTON26 FFJOFS_BUTTON(26) +#define FFJOFS_BUTTON27 FFJOFS_BUTTON(27) +#define FFJOFS_BUTTON28 FFJOFS_BUTTON(28) +#define FFJOFS_BUTTON29 FFJOFS_BUTTON(29) +#define FFJOFS_BUTTON30 FFJOFS_BUTTON(30) +#define FFJOFS_BUTTON31 FFJOFS_BUTTON(31) + +// defines for FFDeviceGetForceFeedbackProperty() and FFDeviceSetForceFeedbackProperty() +// +typedef UInt32 FFProperty; +enum +{ + FFPROP_FFGAIN = 1, + FFPROP_AUTOCENTER = 3 +}; + +// flags for FFDeviceSetCooperativeLevel() +// +typedef UInt32 FFCooperativeLevelFlag; +enum +{ + FFSCL_EXCLUSIVE = 0x00000001, + FFSCL_NONEXCLUSIVE = 0x00000002, + FFSCL_FOREGROUND = 0x00000004, + FFSCL_BACKGROUND = 0x00000008 +}; + +// types used in FFCAPABILITIES structure +// +typedef UInt32 FFCapabilitiesEffectType; +enum +{ + FFCAP_ET_CONSTANTFORCE = 0x00000001, + FFCAP_ET_RAMPFORCE = 0x00000002, + FFCAP_ET_SQUARE = 0x00000004, + FFCAP_ET_SINE = 0x00000008, + FFCAP_ET_TRIANGLE = 0x00000010, + FFCAP_ET_SAWTOOTHUP = 0x00000020, + FFCAP_ET_SAWTOOTHDOWN = 0x00000040, + FFCAP_ET_SPRING = 0x00000080, + FFCAP_ET_DAMPER = 0x00000100, + FFCAP_ET_INERTIA = 0x00000200, + FFCAP_ET_FRICTION = 0x00000400, + FFCAP_ET_CUSTOMFORCE = 0x00000800 +}; + +typedef UInt32 FFCapabilitiesEffectSubType; +enum +{ + FFCAP_ST_KINESTHETIC = 1, + FFCAP_ST_VIBRATION = 2 +}; + + +//----------------------------------------------------------------------------- +// Error return values +//----------------------------------------------------------------------------- + +/*! + @defined FF_OK + @discussion The operation completed successfully. +*/ +#define FF_OK S_OK + +/*! + @defined FF_FALSE + @discussion The operation did not complete successfully. +*/ +#define FF_FALSE S_FALSE + +/*! + @defined FF_DOWNLOADSKIPPED + * @discussion + * The parameters of the effect were successfully updated by + * FFEffectSetParameters, but the effect was not + * downloaded because the FFEP_NODOWNLOAD flag was passed. + */ +#define FF_DOWNLOADSKIPPED ((HRESULT)0x00000003L) + +/*! + @defined FF_EFFECTRESTARTED + * @discussion + * The parameters of the effect were successfully updated by + * FFEffectSetParameters, but in order to change + * the parameters, the effect needed to be restarted. + */ +#define FF_EFFECTRESTARTED ((HRESULT)0x00000004L) + +/*! + @defined FF_TRUNCATED + * @discussion + * The parameters of the effect were successfully updated by + * FFEffectSetParameters, but some of them were + * beyond the capabilities of the device and were truncated. + */ +#define FF_TRUNCATED ((HRESULT)0x00000008L) + +/*! + @defined FF_TRUNCATEDANDRESTARTED + * @discussion + * Equal to FF_EFFECTRESTARTED | FF_TRUNCATED. + */ +#define FF_TRUNCATEDANDRESTARTED ((HRESULT)0x0000000CL) + +/*! + @defined FFERR_DEVICENOTREG + * @discussion + * The device or device instance or effect is not registered. + */ +#define FFERR_DEVICENOTREG REGDB_E_CLASSNOTREG + +/*! + @defined FFERR_INVALIDPARAM + * @discussion + * An invalid parameter was passed to the returning function, + * or the object was not in a state that admitted the function + * to be called. + */ +#define FFERR_INVALIDPARAM E_INVALIDARG + +/*! + @defined FFERR_NOINTERFACE + * @discussion + * The specified interface is not supported by the object + */ +#define FFERR_NOINTERFACE E_NOINTERFACE + +/*! + @defined FFERR_GENERIC + * @discussion + * An undetermined error occurred. + */ +#define FFERR_GENERIC E_FAIL + +/*! + @defined FFERR_OUTOFMEMORY + * @discussion + * Couldn't allocate sufficient memory to complete the caller's request. + */ +#define FFERR_OUTOFMEMORY E_OUTOFMEMORY + +/*! + @defined FFERR_UNSUPPORTED + * @discussion + * The function called is not supported at this time + */ +#define FFERR_UNSUPPORTED E_NOTIMPL + +#ifndef E_PENDING +/*! + @defined E_PENDING + * @discussion + * Data is not yet available. + */ +#define E_PENDING 0x8000000AL +#endif + +/*! + @defined FFERR_DEVICEFULL + * @discussion + * The device is full. + */ +#define FFERR_DEVICEFULL 0x80040201L + +/*! + @defined FFERR_MOREDATA + * @discussion + * Not all the requested information fit into the buffer. + */ +#define FFERR_MOREDATA 0x80040202L + +/*! + @defined FFERR_NOTDOWNLOADED + * @discussion + * The effect is not downloaded. + */ +#define FFERR_NOTDOWNLOADED 0x80040203L + +/*! + @defined FFERR_HASEFFECTS + * @discussion + * The device cannot be reinitialized because there are still effects + * attached to it. + */ +#define FFERR_HASEFFECTS 0x80040204L + +/*! + @defined FFERR_INCOMPLETEEFFECT + * @discussion + * The effect could not be downloaded because essential information + * is missing. For example, no axes have been associated with the + * effect, or no type-specific information has been created. + */ +#define FFERR_INCOMPLETEEFFECT 0x80040206L + +/*! + @defined FFERR_EFFECTPLAYING + * @discussion + * An attempt was made to modify parameters of an effect while it is + * playing. Not all hardware devices support altering the parameters + * of an effect while it is playing. + */ +#define FFERR_EFFECTPLAYING 0x80040208L + +/*! + @defined FFERR_UNPLUGGED + * @discussion + * The operation could not be completed because the device is not + * plugged in. + */ +#define FFERR_UNPLUGGED 0x80040209L + + +// +// Mac OS X specific +// + +/*! + @defined FFERR_INVALIDDOWNLOADID + * @discussion + * The effect index provided by the API in downloadID is not recognized by the + * IOForceFeedbackLib driver. + */ +#define FFERR_INVALIDDOWNLOADID 0x80040300 + +/*! + @defined FFERR_DEVICEPAUSED + * @discussion + * When the device is paused via a call to FFDeviceSendForceFeedbackCommand(), + * other operations such as modifying existing effect parameters and creating + * new effects are not allowed. + */ +#define FFERR_DEVICEPAUSED 0x80040301 + +/*! + @defined FFERR_INTERNAL + * @discussion + * The IOForceFededbackLib driver has detected an internal fault. Often this + * occurs because of an unexpected internal code path. + */ +#define FFERR_INTERNAL 0x80040302 + +/*! + @defined FFERR_EFFECTTYPEMISMATCH + * @discussion + * The IOForceFededbackLib driver has received an effect modification request + * whose basic type does not match the defined effect type for the given effect. + */ +#define FFERR_EFFECTTYPEMISMATCH 0x80040303 + +/*! + @defined FFERR_UNSUPPORTEDAXIS + * @discussion + * The effect includes one or more axes that the device does not support. + */ +#define FFERR_UNSUPPORTEDAXIS 0x80040304 + +/*! + @defined FFERR_NOTINITIALIZED + * @discussion + * This object has not been initialized + */ +#define FFERR_NOTINITIALIZED 0x80040305 + +/*! + @defined FFERR_EFFECTTYPENOTSUPPORTED + * @discussion + * The effect type requested is not explicitly supported by the particular device. + */ +#define FFERR_EFFECTTYPENOTSUPPORTED 0x80040306 + +/*! + @defined FFERR_DEVICERELEASED + * @discussion + * The device has been released. + */ +#define FFERR_DEVICERELEASED 0x80040307 + +#ifdef __cplusplus +} +#endif + +#endif // _FORCEFEEDBACKCONSTANTS_H_ + diff --git a/Frameworks/ForceFeedback.framework/Versions/A/Headers/IOForceFeedbackLib.h b/Frameworks/ForceFeedback.framework/Versions/A/Headers/IOForceFeedbackLib.h new file mode 100755 index 0000000..7bce10c --- /dev/null +++ b/Frameworks/ForceFeedback.framework/Versions/A/Headers/IOForceFeedbackLib.h @@ -0,0 +1,447 @@ +//----------------------------------------------------------------------------- +// File: IOForceFeedbackLib.h +// Contains: Public interfaces for the Force Feedback Plugin architecture . +// Copyright: © 2002 by Apple Computer, Inc. All rights reserved. +// +//----------------------------------------------------------------------------- + +#ifndef _IOFORCEFEEDBACKLIB_H +#define _IOFORCEFEEDBACKLIB_H + +#if PRAGMA_ONCE +#pragma once +#endif + +/*! @header IOForceFeedbackLib.h + @abstract Public Interfaces and constants used to develop Force Feedback plugIns. + @discussion A force feedback device manufacturer might need to implement a plug in + to allow the Force Feedback Library to control the device. This header + file describes the functions that need to be implemented. This interface definition + follows Microsoft Windoes IDirectInputEffectDriver definition wherever it makes sense to do so. + Certain functions may contain more or fewer parameters than the Windows version + +*/ +#include + +__BEGIN_DECLS +#include +#if COREFOUNDATION_CFPLUGINCOM_SEPARATE +#include +#endif + +#include +#include +#include + +//==================================================================================================================== +// The Version of the FF PlugIn API +//==================================================================================================================== +// +enum { + kFFPlugInAPIMajorRev = 1, + kFFPlugInAPIMinorAndBugRev = 0, + kFFPlugInAPIStage = finalStage, + kFFPlugInAPINonRelRev = 0 +}; + +//==================================================================================================================== +// Defines +//==================================================================================================================== +// + +#define FFDEVICESTATE ForceFeedbackDeviceState +#define PFFDEVICESTATE ForceFeedbackDeviceStatePtr + + +// F4545CE5-BF5B-11D6-A4BB-0003933E3E3E +#define kIOForceFeedbackLibTypeID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xF4, 0x54, 0x5C, 0xE5, 0xBF, 0x5B, 0x11, 0xD6, \ + 0xA4, 0xBB, 0x00, 0x03, 0x93, 0x3E, 0x3E, 0x3E) + +// 1C7C5850-BB6A-11D6-B75F-003065FBE6B0 +#define kIOForceFeedbackDeviceInterfaceID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0x1C, 0x7C, 0x58, 0x50, 0xBB, 0x6A, 0x11, 0xD6, \ + 0xB7, 0x5F, 0x00, 0x30, 0x65, 0xFB, 0xE6, 0xB0) + + +//==================================================================================================================== +// Structs +//==================================================================================================================== +// +struct ForceFeedbackDeviceState +{ + UInt32 dwSize; + UInt32 dwState; + UInt32 dwLoad; + +}; + +typedef struct ForceFeedbackDeviceState ForceFeedbackDeviceState; +typedef ForceFeedbackDeviceState * ForceFeedbackDeviceStatePtr; + + +struct ForceFeedbackVersion +{ + NumVersion apiVersion; + NumVersion plugInVersion; +}; + +typedef struct ForceFeedbackVersion ForceFeedbackVersion; +typedef ForceFeedbackVersion * ForceFeedbackVersionPtr; + +//==================================================================================================================== +// Types +//==================================================================================================================== +// +typedef UInt32 FFEffectDownloadID; + + +//==================================================================================================================== +// +// ForceFeedback Device Interface Functions available in version 1.0 of architecture +// +//==================================================================================================================== +// +#define IOFORCEFEEDBACKDEVICE_FUNCS_100 \ + \ + HRESULT (*ForceFeedbackGetVersion)( void * self, \ + ForceFeedbackVersion * version); \ + \ + HRESULT (*InitializeTerminate)( void * self, \ + NumVersion forceFeedbackAPIVersion,\ + io_object_t hidDevice, \ + bool begin ); \ + \ + HRESULT (*DestroyEffect)( void * self, \ + FFEffectDownloadID downloadID ); \ + \ + HRESULT (*DownloadEffect)( void * self, \ + CFUUIDRef effectType, \ + FFEffectDownloadID * pDownloadID, \ + FFEFFECT * pEffect, \ + FFEffectParameterFlag flags ); \ + \ + HRESULT (*Escape)( void * self, \ + FFEffectDownloadID downloadID, \ + FFEFFESCAPE * pEscape ); \ + \ + HRESULT (*GetEffectStatus)( void * self, \ + FFEffectDownloadID downloadID, \ + FFEffectStatusFlag * pStatusCode ); \ + \ + HRESULT (*GetForceFeedbackCapabilities)( void * self, \ + FFCAPABILITIES * pCapabilities ); \ + \ + HRESULT (*GetForceFeedbackState)( void * self, \ + ForceFeedbackDeviceState * pDeviceState ); \ + \ + HRESULT (*SendForceFeedbackCommand)( void * self, \ + FFCommandFlag state ); \ + \ + HRESULT (*SetProperty)( void * self, \ + FFProperty property, \ + void * pValue ); \ + \ + HRESULT (*StartEffect)( void * self, \ + FFEffectDownloadID downloadID, \ + FFEffectStartFlag mode, \ + UInt32 iterations ); \ + \ + HRESULT (*StopEffect)( void * self, \ + FFEffectDownloadID downloadID ); + +//==================================================================================================================== +// +// END OF DeviceInterface Functions available in version 1.0 of this API +// +//==================================================================================================================== +// +struct IOForceFeedbackDeviceInterface { + IUNKNOWN_C_GUTS; + IOFORCEFEEDBACKDEVICE_FUNCS_100 +}; + +typedef struct IOForceFeedbackDeviceInterface IOForceFeedbackDeviceInterface; +typedef IOForceFeedbackDeviceInterface * IOForceFeedbackDeviceInterfacePtr; + + +//==================================================================================================================== +// +// ¥¥¥¥¥ The following is #ifdef out. It is here so that we can header doc this file without intruding in its +// ¥¥¥¥¥ readability. +// +//==================================================================================================================== +// +#if 0 + +struct IOForceFeedbackDeviceInterface { + IUNKNOWN_C_GUTS; + +/*! @function ForceFeedbackGetVersion + @abstract This function is used to determine driver and API version information. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param version Pointer to ForceFeedbackVersion structure that is to receive the required info. See the structure description for details. + @result Returns FF_OK if successful, or an error value otherwise. +*/ + HRESULT (*ForceFeedbackGetVersion) (void * self, ForceFeedbackVersion * version); + + +/*! @function InitializeTerminate + @abstract This function is used to "create and destroy" particular device instances. It provides the FF plug-in driver with all the necessary start-up parameters. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param forceFeedbackAPIVersion The version number of FF API that loaded the effect driver. The plugIn should check that the major version of the forceFeedbackAPI version is the same as the major version of the API at the time the plugIn was compiled. If the major versions are different, then the plugIn API has changed and the plugIn will NOT be compatible with it. +
+If begin is false, this parameter is ignored. + @param hidDevice A device object that can be used by the FF plug-in to establish a connection to and communicate with the device. The caller will release the hidDevice device object with a call to IOObjectRelease() once the FF plug-in completes its InitializeTerminate processing, so a FF plug-in implementation should not make a copy of the io_object_t variable with the intention of using it outside the context of this call. +
+If begin is false, this parameter is ignored. (You can pass NULL.) + @param begin Nonzero if access to the device is beginning. Zero if the access to the device is ending. The FF API will call InitializeTerminate( begin=TRUE) when a FF device is first selected for use, and InitializeTerminate( begin=false) when the FF device is no longer needed. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INVALIDPARAM +
FFERR_NOINTERFACE +
FFERR_OUTOFMEMORY +
+*/ + HRESULT (*InitializeTerminate)(void * self, NumVersion forceFeedbackAPIVersion, io_object_t hidDevice, bool begin ); + + +/*! @function DestroyEffect + @abstract This function commands the device to "destroy" a currently downloaded effect. The effect ID and any data that is associated with the effect are freed and available for reallocation. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param downloadID Indicates the effect ID that was obtained from the device when the effect was downloaded. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INVALIDDOWNLOADID +
FFERR_GENERIC +
FFERR_INTERNAL +
+*/ + HRESULT (*DestroyEffect)(void * self, FFEffectDownloadID downloadID ); + + +/*! @function DownloadEffect + @abstract This function sends an effect to the device. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param effectType Indicates the type of effect being created. Valid UUIDs are listed as kFFEffectType_* constants in the ForceFeedbackConstants.h file. (Supported effect types include Sine, Square, Triangle, SawtoothUp, SawtoothDown, Constant, Spring, Damper, etc.). + @param pDownloadID On entry, this parameter points to the handle of the effect being downloaded. If the parameter points to a zero, then a new effect is downloaded. On exit, the FFEffectDownloadID pointed to by this parameter contains the new effect handle. On failure, the FFEffectDownloadID pointed to by this parameter is set to zero if the effect is lost, or left alone if the effect is still valid with its old parameters. Note that zero is never a valid effect handle. + @param pEffect The new parameters for the effect. +
+IMPORTANT NOTE: Unlike the IDirectInputEffectDriver specification, the axis and button values are NOT converted to object identifiers before they are handed over to the driver. In this case, the only supported method used to assign triggers and output axes is through object offsets, defined by the FFJOFS_* constants. Therefore, if a button is assigned to trigger an effect, FFEFFECT.dwTriggerButton will contain a constant of the form FFJOFS_BUTTONn. Similarly, output axes will be identified in FFEFFECT.rgdwAxes[n] as FFJOFS_X, FFJOFS_Y, etc. + @param flags Specifies which portions of the effect information have changed from the effect already on the device. This information is passed to drivers to allow for the optimization of effect modification. If an effect is being modified, a driver may be able to update the effect in its original position and transmit to the device only the information that has changed. Drivers are not, however, required to implement this optimization. All members of the FFEFFECT structure that are pointed to by the pEffect parameter are valid, and a driver may choose simply to update all parameters of the effect at each download. There may be zero, one, or more of the following: +
+
FFEP_DURATION +
Indicates the dwDuration member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_SAMPLEPERIOD +
Indicates the dwSamplePeriod member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_GAIN +
Indicates the dwGain member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_TRIGGERBUTTON +
Indicates the dwTriggerButton member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_TRIGGERREPEATINTERVAL +
Indicates the dwTriggerRepeatInterval member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_AXES +
Indicates the cAxes and rgdwAxes members of the FFEFFECT structure are being downloaded for the first time or have changed since their last download. +
+
FFEP_DIRECTION +
Indicates the cAxes and rglDirection members of the FFEFFECT structure are being downloaded for the first time or have changed since their last download. (The dwFlags member of the FFEFFECT structure specifies, through FFEFF_CARTESIAN or FFEFF_POLAR, the coordinate system in which the values should be interpreted.) +
+
FFEP_ENVELOPE +
Indicates the lpEnvelope member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. If this flag is set and the lpEnvelope member is a NULL pointer, then the effect is being created with no envelope, or the existing envelope is being deleted. +
+
FFEP_TYPESPECIFICPARAMS +
Indicates the cbTypeSpecificParams and lpTypeSpecificParams members of the FFEFFECT structure are being downloaded for the first time or have changed since their last download. +
+
FFEP_STARTDELAY +
Indicates the dwStartDelay member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_START +
Indicates that the effect is to be restarted from the beginning after the parameters of the effect have been updated. Note that the FFEP_NODOWNLOAD flag overrides the FFEP_START flag. +
+
FFEP_NORESTART +
If this flag is not specified, the effect device driver is permitted to restart the effect if doing so is necessary to change the specified parameters. Note that the FFEP_NODOWNLOAD and FFEP_START flags override this flag. +
+
FFEP_NODOWNLOAD +
Suppresses the automatic download that is normally performed after the parameters are updated. If this flag is set, the driver should validate parameters without performing an actual download. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_INVALIDDOWNLOADID +
FFERR_INTERNAL +
FFERR_EFFECTTYPEMISMATCH +
+*/ + HRESULT (*DownloadEffect)( void * self, CFUUIDRef effectType, FFEffectDownloadID * pDownloadID, +FFEFFECT * pEffect, FFEffectParameterFlag flags ); + + +/*! @function Escape + @abstract This function escapes to the driver. This method is called in response to an application invoking the FFEffectEscape or FFDeviceEscape methods. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param downloadID Specifies the effect at which the command is directed, or zero if the command is directed at the device itself and not any particular effect. + @param pEscape Pointer to a FFEFFESCAPE structure that describes the command to be sent. On success, the cbOutBuffer member contains the number of output buffer bytes actually used. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_UNSUPPORTED +
+*/ + HRESULT (*Escape)( void * self, FFEffectDownloadID downloadID, FFEFFESCAPE * pEscape ); + + +/*! @function GetEffectStatus + @abstract This function returns the device effect's status. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param downloadID Indicates the effect to be queried. + @param pStatusCode Receives the effect status. The FFEffectStatusFlag pointed to by this parameter should be filled in with one of the following values: +
+
FFEGES_PLAYING +
The effect is still playing. +
+
FFEGES_NOTPLAYING +
The effect is not playing. + @result Returns FF_OK. +*/ + HRESULT (*GetEffectStatus)( void * self, FFEffectDownloadID downloadID, FFEffectStatusFlag * pStatusCode ); + + +/*! @function GetForceFeedbackCapabilities + @abstract This function escapes to the driver. This method is called in response to an application invoking the FFEffectEscape or FFDevicEscape methods. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param pCapabilities Pointer to a FFCAPABILITIES structure that should be filled in with version information describing the hardware, firmware, and driver. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INTERNAL +
FFERR_NOINTERFACE +
+*/ + HRESULT (*GetForceFeedbackCapabilities)( void * self, FFCAPABILITIES * pCapabilities ); + + +/*! @function GetForceFeedbackState + @abstract This function returns the state of the device. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param pDeviceState Pointer to a ForceFeedbackDeviceState structure that receives the device state. FF API sets the dwSize member of the ForceFeedbackDeviceState structure to sizeof(ForceFeedbackDeviceState) before calling this method. + @result Returns FF_OK. +*/ + HRESULT (*GetForceFeedbackState)( void * self, ForceFeedbackDeviceState * pDeviceState ); + + +/*! @function SendForceFeedbackCommand + @abstract This function sends a command to the device. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param state Indicates the command being sent. That command can be one of the following: +
+
FFSFFC_RESET +
Indicates that playback of any active effects should be been stopped and that all effects should be removed from the device. Once the device has been reset, all effects are no longer valid and must be re-created. +
+
FFSFFC_STOPALL +
Indicates that playback of all effects should be stopped. Sending the FFSFFC_STOPALL command is equivalent to invoking the FFEffect_Stop method on all effects that are playing. If the device is in a paused state, the device driver is permitted to lose the paused state. +
+
FFSFFC_PAUSE +
Indicates that playback of all effects should be paused. When effects are paused, time "stops" until the FFSFFC_CONTINUE command is sent. For example, suppose an effect of five seconds' duration is started. After one second, all effects are paused. After two more seconds, all effects are continued. The effect should then play for four additional seconds. While a force-feedback device is paused, starting a new effect or modifying existing ones can cause the paused state to be lost. +
+
FFSFFC_CONTINUE +
Indicates that playback should be resumed at the point at which it was interrupted for those effects that were paused by a previous FFSCFFC_PAUSE command. +
+
FFSFFC_SETACTUATORSON +
Indicates that the device's force-feedback actuators should be enabled. +
+
FFSFFC_SETACTUATORSOFF +
Indicates that the device's force-feedback actuators should be disabled. If successful, force-feedback effects are "muted". Note that time continues to elapse while actuators are off. For example, suppose an effect of five seconds' duration is started. After one second, actuators are turned off. After two more seconds, actuators are turned back on. The effect should then play for two additional seconds. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INTERNAL +
FFERR_INVALIDPARAM +
+*/ + HRESULT (*SendForceFeedbackCommand)( void * self, FFCommandFlag state ); + + +/*! @function SetProperty + @abstract This function sets properties that define the device behavior. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param property The following property values are defined for a FF device: +
+
FFPROP_AUTOCENTER +
Specifies whether the actuated FF axes are self-centering. This property controls the deviceÕs Òdefault centering springÓ. +
The pValue member points to a UInt32 and can be one of the following values. +
+
0 - OFF: The device should not automatically center when the user releases the device. An application that uses force feedback should disable autocentering before playing effects. +
+
1 - ON: The device should automatically center when the user releases the device. +
+
Not all devices support the autocenter property. +
+
FFPROP_FFGAIN +
Sets the gain for the device. +
+
The pValue member points to a UInt32 that contains a gain value that is applied to all effects created on the device. The value is an integer in the range from 0 through 10,000, specifying the amount by which effect magnitudes should be scaled for the device. For example, a value of 10,000 indicates that all effect magnitudes are to be taken at face value. A value of 9,000 indicates that all effect magnitudes are to be reduced to 90% of their nominal magnitudes. +
+
Setting a gain value is useful when an application wants to scale down the strength of all force-feedback effects uniformly, based on user preferences. + @param pValue Address of the location where the property value is to be read. This function will assume that the data is valid, and of the correct type. + @result If the method succeeds, the return value is FF_OK or FFERR_UNSUPPORTED. +If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
+*/ + HRESULT (*SetProperty)( void * self, FFProperty property, void * pValue ); + + +/*! @function StartEffect + @abstract This function commands the device to play back an effect that was previously loaded. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param downloadID Indicates the effect to be played. + @param mode Specifies how the effect is to affect other effects. Only the mode listed below can be used; all other modes are reserved. For example, the driver never receives the FFES_NODOWNLOAD flag because it is managed by the FF API and not the PlugIn driver. This parameter can be zero, one, or more of the following flags: +
+
FFES_SOLO +
Indicates that all other effects on the device should be stopped before the specified effect is played. If this flag is omitted, the effect is mixed with existing effects that have already started on the device. + @param iterations Specifies the number of times to perform the effect. If the value is FF_INFINITE, then the effect should be repeated until explicitly stopped or paused. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INTERNAL +
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_GENERIC +
FFERR_INVALIDDOWNLOADID +
+*/ + HRESULT (*StartEffect)( void * self, FFEffectDownloadID downloadID, FFEffectStartFlag mode, UInt32 iterations ); + +/*! @function StopEffect + @abstract This function commands the device to stop an effect that was previously started. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param downloadID Indicates the effect to be stopped. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INTERNAL +
FFERR_GENERIC +
FFERR_INVALIDDOWNLOADID +
+*/ + HRESULT (*StopEffect)( void * self, UInt32 downloadID ); +}; + +#endif // #if 0 ¥¥¥ Used for header doc'ing only + +__END_DECLS + +#endif /* ! _IOFORCEFEEDBACKLIB_H */ diff --git a/Frameworks/ForceFeedback.framework/Versions/A/Resources/Info.plist b/Frameworks/ForceFeedback.framework/Versions/A/Resources/Info.plist new file mode 100755 index 0000000..ce08864 --- /dev/null +++ b/Frameworks/ForceFeedback.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ForceFeedback + CFBundleGetInfoString + 1.0.0, Copyright Apple Computer, Inc. 2002 + CFBundleIdentifier + com.apple.ForceFeedback + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ForceFeedback Framework + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0.0 + + diff --git a/Frameworks/ForceFeedback.framework/Versions/A/Resources/version.plist b/Frameworks/ForceFeedback.framework/Versions/A/Resources/version.plist new file mode 100755 index 0000000..69ea4de --- /dev/null +++ b/Frameworks/ForceFeedback.framework/Versions/A/Resources/version.plist @@ -0,0 +1,18 @@ + + + + + BuildVersion + 70 + CFBundleShortVersionString + 1.0.0 + CFBundleVersion + 1.0.0 + ProjectName + ForceFeedback + ReleaseStatus + Beta + SourceVersion + 1000305 + + diff --git a/Frameworks/ForceFeedback.framework/Versions/Current/ForceFeedback b/Frameworks/ForceFeedback.framework/Versions/Current/ForceFeedback new file mode 100755 index 0000000000000000000000000000000000000000..b1c427c4cf97cbb0bdb0118121c3365924fe79d3 GIT binary patch literal 19208 zcmeHP4{)2sm4Eu=1`2iA)^gG-_g6(~)C2NZ4`ZivbrqJu?lJ6QOYRQv z{od|=(r3js;ih*pH)9RUzTJJ_dvD*qef#!(&iBc0|MMS-=q42Y%|p4K$a)_24^T|_ z&l(7{Z|Z1AOa1olW1w2KL|u$V5sHO71A$~Xm1Ic%u719FoM=^)h-)(Icp6!C5H#YE z(7;gNwpcVUkR050HI2_Z@aS$Lu8lOvrifGq0-=FqBGUh$>bRQ5`WG;?l}OY%IgIoG zvkoQ#fkt1uPZ2_OSm?kGi098Wu?~3ttV77(6-)*hlE3MnrxK+{18=a)J<~N5?b2IJ z^C}teJkPh9YXc4AGtpo`=`o&6Oh=;(*nZI9+Cam^^AUCt2=rqSu@a>Cr!7dVgf$qWn&~$R}Os$ZEYXc3_b^JX4u%6w<1)WA8JwU@^RC8^hAOE zeM@9pBA6Ij-;@aUg&&P2dI#1w#S)=#Q#jnUEg0%u*R2n%|7tif5Q+564VgL}s5$^SzrR$?3_9 zA)RK8r1?aG>H#s$!GXm3Xk;4~sj78%t%F%dw(%okjmn|(all_9YI4E^E&zrPqE;0C zEmVc=^Hvnpja90C6Ezlh6R*p9qJ}K$+feUD4enl4bh9dU^t%Bwoy91u>$%^Y2L4}Z zAZ;@rzUz4^8s2R_oVHmG4{M=R{o{7ZJbtBp_%X}jbcsc8`|r`L&f)KdQky3y-^xAL zBcH49#WTHEoWl{zVaDU}(Q}g@Wldyzs$z1Cd5l~zANGvES%y~cc4x>7I>$1oUD!Fk zgH+}jv6B|M;$^;|QK6Zr$6Z04EZ0uZxE~!?CNDDG^s_5dOgDXe zZ7SWhH0ADOTDKia4=)`8{c7zwvZDPk(?;7i`Wz9{9Qod_Q%sj>9tADnRONV~UC66o z9^U#p?Ua6QWh%4gvWuMyWEq35#&*64y`3Pc(}+e6{W|5RRWGY~y`lwaOvrJNj(DE8 zlY7_Y8jMGjY)^6D=t*kScK!Q1?gQiiaUnNo`>FC*YK~hy&x7X} z%C6hS(f{(usSi_(2Y6WYpCA+KW#k3Xw<*0{=%y0#wgTtIYRly0h_=K&@}mz~-U|8b zswD<_ZRnp5{k%D{^L^Ia30-gcdK^DFd0MQ;Ua=mX=|`8QG%Hohb)IJh>=N+7qARSg zx)by+@H^ZZeSo?Va^4TUopPV0&RU{3YMu0xS})yLH%8xqPTbI^WAp%d>N?57da3i$ z=xC7qbxvv<^-)V5(XmmiC(m=#MD2cBxrpsSdsOJ^;dG~%vrD^~T%JyiIzwc^VPf%S zic*;`QMKNeS;P4B(hRZ%jk2*^EECJavalR1gXDkf(|P_Y|DgDHg1=4Y<)X<+-wx}Q z0-1`v8S8m%uR*3tqS`g9?N#&dar!dWH#3!F)oJMcezIJeLFR4OE_1~>gUt0Tv-hB> zYX-WZ&p`LFJl$JAP;^UXpxgBs=-zIi`-G%RugpL3dzcA3fL($zj1KsY=KsS@8 zTXBZzVox^~tp5$(jCsoXWA9KEt+x9z=C=Un?5Bzzf8I|f_TAI%qX(~Dt`)yB$hGNH z)~Dw)(A|@#>-_DftWV@K(5*Glefm?@=b>w-yWC*^PGSF8pBD<&XR$Y9YMgn0nyRMT zpT3OAj{e-*>HF4~p(|L^5`90*b*A&^vlsMDps%c;?=|?USJ;Od{AaImzHA#PjkEiz zWrp=%u}Pgrtp)RjT~f=Gc_aFEA!3J)Y9L!~Zo|&6?Hyio|GQ~;Qk>`IkTEwGz&7^L zI7^P;92xr|&JF#nJ$_*F9gasJuPvQgI)roG%jYhi7aPx-_>A4naRh2D{q)KdpRwC6 zYs|mIg+1auNcQ?pje@;o@soKRXUsN1QfdV)4+GGFG&@~|x6@fFPd9h~zi%-M^1TtMx{TsqLdhiReh z!MyBfw}S4oX#2(dh|Xh!gR6&(80Q*dq-(9>~XX1t4E5+Fr62d2dDkpqL9{AI!xJo5_wIrxG{(Dr)QY^G8$J z<%p4rFn`2LnF`vyXCv8$S8hg(N0fPt%Jg`b<1W~BCHU=jKSyPmm14ZgIL>jhjHj0T zV&wZAcaf80##*dF?V8_rX!Efa%gH|a_lQ@1F80Hl!=bO`VyhowFK}$dF*NT9j@k4W z^v*FT8|%VxFYkxYF&WQbP8WEuA%3=JuO~a;uFOX44e-KPIrL1~`DDXG>CVFO~D&2F@#j-gUo$%|i!kg+AVdjk-e&GQ8f(E~EK>39O(k~#slYSvHonI*5&$he${iE;;AHD$@ zOfu#-jX_US`~m28V2`|xy`J|8;K}@WuVR0DMh!lP`TD869yDk63801f{t0}-;-Bk2 zf#;I<35)mfoY)>=BX9k0`U9RX>&8!uoAdtQ=0AQme{k~wu?Fx5kk`R`w$QdPPHBsU z?dnbaZu3LflGuNy$+KxM-Io65(jon9s`J98e2BqeQ`m!J>C<0KjW&VCzLlx;Yim=& z&UTn;u!ep=E&7=8*k_<0e#hik=fK(y<1YFDS?kWg2h^keb*e^jqEw<(`JSY%kzMb@ zZ!EYw{S6T(wqsv7r7aQeV~a9qR~p(6qg`ca2hpxJw7(+nb&Hxuygy@q^pv)gO0vtS zWb`P?tI*Gr;+$~fj%;IJ2))=*TiHjluX5wQg1U_L1)Lfb7m5R=9Hj&_z1laiw=4gF zb=l)SMpo7}bSiQKBR~Ey1wZO=pS4ULg?)|uf!?)$me?2~eEF42|Ok(W}S&CJ@VFLZ^A4}jLS>DD>J(XaO3%@*r z|9eN^Lr=ih{h#hXPh-p~@3mAVebi0=pXD z*PFP{gNAPFub-T}B5ZtSJ$qmeC7dV1nt0hZP&YC!HGfxb{-BF3Fi9+=#i{W9&oi53`)Qo^rMlUOJ@n0gV={8PCVW`w@2L z$*eN$f5?PAP^Co>ue^cv_!j&U{1C61`w;dj{F1&Ga&ls?80dSo$Aq5YPs|p!1MqYq zmdg7W$)lWkC|k(wFQ$1sGdaO?H~6nkzQ;^I|Dsmd2j_VtKg`LuqsW84JU{L`SX9M( zuI>cZ5i;@q&eX&IAYL}eQK{P`a5?YhuH`!r(RbhrIREB>p6^H7;YJQl?Blc4iM9pt z$s1_9mUs!yF(D;4#n47EBRVjUX}x6qp0}~(N@5h@3_o+nSu9^fwvhsviF#; z;3;#Bg}E_71LwiJh`ro(oya`~k#qFojPoJq=tSfY_vE!&z#3@*K5pI6=p7 zZ^M0U;ekBw8$LGhMh@E2S-^X0{tWz>7xQ7AG9Tu_^qIDt+d`j#{(b{}!~+&8pg%Q_ zc1`pb$o$7JuiFjv2Kw-gW{zKtx|^C$yEginy!;E#80b4e-&;U`YF_Qy=vNr%4;$!v zktaJ_K!0j}?3(D8oHWp1W}vTuzE(hgYM$)c=m+!k7aYsehvAdSSwMekzU30^;pOUBI{g$);t8HKH?dyF8`ui1qTipp8 z37g@Sko!+0H-)TXsKH;aRJqqUIbvVf+CX~MR+E!Gxr8Dy%KG8KKmIXswj zhsxLG-XXJ%y&jzWjfnB`K4pyWCF!GU5$Bm+m2snKJoELO?G&?Z`F2=Nxr!{4kVC_r zLcb$Iw?&+9;k!dM`t`da_h(dp4f^#vBlkyCzZ?Df-I4n_m&|m$;=Y1+y_+XL`h&c0 znLkSRF2%Z7yg6S6KL*_LfllGe&T8-F_QNIU+Ntd80^6ppCu#rYkEYoFYUB$s*FTN@ zo1eML{-G=E0f$(}<*>nJ_6_h8h=;5}neVU;=WGnP(q7CR!WPB*dFvv~(TjbT&TIu8 zu@*Q#u&>zeaE}oC0yZ!K-!*l=U&s61T*B+J%C0(l#cO#Hqad&+XZK}NNwOf^iO>0Zm8f_`j!Hj*2%@>$@3{&K!j z$#NciofwyAg9G~$=fglJ&W3{&<^3pq&AERZ@j z?-T0}JnWw`F~{w>eH;~gSLoWjW}wrIy#`<4pc>F>bS;&+A0OV4@cO#{8EcQ+)yRXt zOo_W9@)J0Ji0_>6_vFUAf}_~u#`_}p$uj`YDW4$nU5qDuf}Xd^`-E}f6OgB1S=c9F zp2i%-7|SB>e#l*64S@H!rgBZd^>RKyj+-rzJuYO0Y%D9!LCDJY+x)$@g7-R}74sZG z%z}A#q{ryC_CqT^QFCp@^CIuY&yRfj{ge~u4WFT)pV4?eG%HlNoV7l3{X%c;*_`c!gXrL%*0N0Yyc=kst<54P-f=u4lA zF$aY>f#0GWR^eo4!HFxJ z_$)ZB3a51zoN9$rJqwOq;n-)!dHbTodHdolI1>tIViufng)=@2PFCS$XTgapocJs_ ztqP}g7MyB@Q#}igUE$bg#+kS%aV9R#f-|9TCKv~QOOC$-4}^lzDE}4pU^EI#iiZcT`Wxjsw-9PRJB9Z<*F{@8Z!O$LgYO0@9#?h zpI(TZDPa68zf=8oB5Uz-{Oe!j9WW>B3JDiq0Q?07p9TD93IwiB?X zVB|)uqY|E91^9@BuWJE(O2Uz;zOKqyPsc zyp-{GO86EB;DZt_e+BU0s{UsH|5CyZ{`bsRRR0OA-7TvB6kwNxmpK7@6r2RSMZzmF zUsF`Vt2+QIzH6g^pOpQsR={Hl9s@is;j#(9Ka#NhDZoElKqeFCf&l+cz{m;V)w@-~ zk*$CiNO;A2fXgNP1mrhY2^je#z<0|2L%RU)5-@U1fS;AHhv~c~ z;pR(#Cl-*|#Ca>gA4)ihd08L>_hVXQsRlmD+?3_M1!OUC-V6O5+|RiyzLm^x8dA8(_40DeJ~Zj^qM1WFQk`1kE}C(2Ji2jiADlv6O1NqjoP zh5jC*+gYePP`-dtgMxq4PM=3vhr&3YLs^4@f8$PgQ_Qb==vEYD>BWaAR-uN@X)Vg1 zgpLM6_RVKeH!%Xw zq3UI-UasmDs&=ZHzYhSqmSNP!AH0P46&pLJ!j^BN&Cj!}jL*7d{COz+V|n%e3lMz% zLIGUyx-brZ8-nX;@X<>a3)UH>2xT710xQ&MhAL6)C^w?qgi?x9hO!9dW|YM!@)}VY2Wi5&eRY?vPMJA{t(fUkyeFq2Y$6O%D$Sp_B&Q5EyI|-_`*ED7diQAP4i^Qi8h&lfi9K zL2=7{Ewb;=BgvkoNHi?J4$>M-_V7~}W`k(EFWfDfTbdgsdQ&3SmnXgj{lII$=Twrx z{vc{^iCA@5rrYg)i0Is??QqG2Ga9{xQ2q(h*ym`74Vf??hp~)AG#zMhl zEYTS54h}}Kw0(HR6T`=G`oevo_z;PgI=8Qj5g0s#Eq2#nB-#~D+#SRxXA<{r<1W@5 z5TcR(UT3%~0%H7BS0Ebv#*qHao^6r-E_?+k5N4SJ@mQokDUkwwJ@Um-peGyzVcE;y z=Ltk(vEISBM8-fMV0h&eXoyD#2e_bLa5FqYq3%BU#U`C?PdJLbC25OKITZ{99t^~# zX@Z__Fd1vdSArt_;)^z5(0nfzm=~27adQ~{pfMI6P>bacJ`(1B3cyq&_zF&#UwO5~ Z!=XrbBqTNw+d(YO3l>S_T-8-G|8HW8#+m>C literal 0 HcmV?d00001 diff --git a/Frameworks/ForceFeedback.framework/Versions/Current/Headers/ForceFeedback.h b/Frameworks/ForceFeedback.framework/Versions/Current/Headers/ForceFeedback.h new file mode 100755 index 0000000..59b8b5d --- /dev/null +++ b/Frameworks/ForceFeedback.framework/Versions/Current/Headers/ForceFeedback.h @@ -0,0 +1,816 @@ +//----------------------------------------------------------------------------- +// File: ForceFeedback.h +// Contains: Public interfaces for ForceFeedback technology. +// Copyright: © 2002 by Apple Computer, Inc. All rights reserved. +// +//----------------------------------------------------------------------------- + +#ifndef _FORCEFEEDBACK_H_ +#define _FORCEFEEDBACK_H_ + +#if PRAGMA_ONCE +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! @header ForceFeedback.h + @abstract Public Interfaces to the Force Feedback implementation in Mac OS X. + @discussion The Force Feedback API allows developers to control Force Feedback devices attached to the system. It is a distilled version of the Force Feedback functionality found in Microsoft's DirectInput API. Developers familiar with that API should find this API to be similar. + +*/ + +#include +#if COREFOUNDATION_CFPLUGINCOM_SEPARATE +#include +#endif + +#include +#include +#include + +//----------------------------------------------------------------------------- +// The Version of the FF API +//----------------------------------------------------------------------------- + +enum { + kFFAPIMajorRev = 1, + kFFAPIMinorAndBugRev = 0, + kFFAPIStage = finalStage, + kFFAPINonRelRev = 0 +}; + +//----------------------------------------------------------------------------- +// Effect definition structures +//----------------------------------------------------------------------------- + +struct FFCONSTANTFORCE +{ + LONG lMagnitude; +}; +typedef struct FFCONSTANTFORCE FFCONSTANTFORCE; +typedef FFCONSTANTFORCE * PFFCONSTANTFORCE; + +struct FFRAMPFORCE +{ + LONG lStart; + LONG lEnd; + +}; +typedef struct FFRAMPFORCE FFRAMPFORCE; +typedef FFRAMPFORCE * PFFRAMPFORCE; + +struct FFPERIODIC +{ + DWORD dwMagnitude; + LONG lOffset; + DWORD dwPhase; + DWORD dwPeriod; + +}; +typedef struct FFPERIODIC FFPERIODIC; +typedef FFPERIODIC * PFFPERIODIC; + +struct FFCONDITION +{ + LONG lOffset; + LONG lPositiveCoefficient; + LONG lNegativeCoefficient; + DWORD dwPositiveSaturation; + DWORD dwNegativeSaturation; + LONG lDeadBand; + +}; +typedef struct FFCONDITION FFCONDITION; +typedef FFCONDITION * PFFCONDITION; + +struct FFCUSTOMFORCE +{ + DWORD cChannels; + DWORD dwSamplePeriod; + DWORD cSamples; + LPLONG rglForceData; + +}; +typedef struct FFCUSTOMFORCE FFCUSTOMFORCE; +typedef FFCUSTOMFORCE * PFFCUSTOMFORCE; + +struct FFENVELOPE +{ + DWORD dwSize; /* sizeof(FFENVELOPE) */ + DWORD dwAttackLevel; + DWORD dwAttackTime; /* Microseconds */ + DWORD dwFadeLevel; + DWORD dwFadeTime; /* Microseconds */ + +}; +typedef struct FFENVELOPE FFENVELOPE; +typedef FFENVELOPE * PFFENVELOPE; + +// IMPORTANT NOTE: OBJECT IDS cannot be used to identify trigger buttons +// in FFEFFECT.dwTriggerButton, and output axes in FFEFFECT.rgdwAxes[n]. +// Please use object offsets (FFJOFS_* constants), the only supported method. +struct FFEFFECT +{ + DWORD dwSize; /* sizeof(FFEFFECT) */ + DWORD dwFlags; /* FFEFF_* */ + DWORD dwDuration; /* Microseconds */ + DWORD dwSamplePeriod; /* Microseconds */ + DWORD dwGain; + DWORD dwTriggerButton; /* or FFEB_NOTRIGGER */ + DWORD dwTriggerRepeatInterval; /* Microseconds */ + DWORD cAxes; /* Number of axes */ + LPDWORD rgdwAxes; /* Array of axes */ + LPLONG rglDirection; /* Array of directions */ + PFFENVELOPE lpEnvelope; /* Optional */ + DWORD cbTypeSpecificParams; /* Size of params */ + void* lpvTypeSpecificParams; /* Pointer to params */ + DWORD dwStartDelay; /* Microseconds */ + +}; +typedef struct FFEFFECT FFEFFECT; +typedef FFEFFECT * PFFEFFECT; + +struct FFEFFESCAPE +{ + DWORD dwSize; + DWORD dwCommand; + void* lpvInBuffer; + DWORD cbInBuffer; + void* lpvOutBuffer; + DWORD cbOutBuffer; + +}; +typedef struct FFEFFESCAPE FFEFFESCAPE; +typedef FFEFFESCAPE * PFFEFFESCAPE; + +// NOTE: this structure has no DirectInput equivalent +struct FFCAPABILITIES +{ + NumVersion ffSpecVer; // Version of specification supported by the driver + UInt32 supportedEffects; // FFCAP_ET_*; including emulated effects + UInt32 emulatedEffects; // FFCAP_ET_*; driver-emulated effects + UInt32 subType; // FFCAP_TYPE_* + UInt32 numFfAxes; + UInt8 ffAxes[32]; + UInt32 storageCapacity; // number of effects that can be stored + // by the driver/device + UInt32 playbackCapacity; // number of effects that can be _simultaneously_ + // played back by the driver/device + NumVersion firmwareVer; // device firmware version, vendor-defined + NumVersion hardwareVer; // hardware version, vendor-defined + NumVersion driverVer; // driver version, vendor-defined + +}; +typedef struct FFCAPABILITIES FFCAPABILITIES; +typedef FFCAPABILITIES * PFFCAPABILITIES; + + + +//----------------------------------------------------------------------------- +// Object reference pointers +//----------------------------------------------------------------------------- + +// FFDeviceObjectReference and FFEffectObjectReference are opaque handles +// to objects created and maintained by the FF API. +// A FFDeviceObjectReference is obtained through a call to FFCreateDevice and +// refers to a specific attached device supporting force feedback. This +// reference may be passed to any of the "FFDevice" functions (below). When +// you are through with it, call FFReleaseDevice to release the memory. +// Similarly, a FFEffectObjectReference is obtained through a call to +// FFDeviceCreateEffect and refers to a created force feedback effect on a +// particular device. This reference may be passed to any of the "FFEffect" +// functions. Call FFDeviceReleaseEffect to unload the effect and clean up +// its memory. - Jeff Mallett 9/25/02 +// +typedef struct {} __FFDHIDDEN, * FFDeviceObjectReference; +typedef struct {} __FFEHIDDEN, * FFEffectObjectReference; + + +//----------------------------------------------------------------------------- +// FF (general) function prototypes +//----------------------------------------------------------------------------- + +/*! @function FFCreateDevice + @abstract Creates a new API device object from an OS object in preparation to use the device for force feedback. + @param hidDevice Pointer to a HID device object. + @param pdeviceReference Address of a variable to receive an opaque reference handle to a new device object. This reference can be used in subsequent calls to FFDevice* functions + @result If the method succeeds, and the device supports FF, the return value is FF_OK. +If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOINTERFACE +
FFERR_OUTOFMEMORY +
FFERR_INTERNAL +
+ @discussion When you are finished with the device, FFReleaseDevice must be called on the reference received in this function to dispose of the API device object. +*/ + +extern HRESULT +FFCreateDevice( + io_service_t hidDevice, + FFDeviceObjectReference * pDeviceReference + ); + + +/*! @function FFReleaseDevice + @abstract Disposes of an API device object created with FFCreateDevice. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @result If the method succeeds, and the device supports FF, the return value is FF_OK. +If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOINTERFACE +
FFERR_OUTOFMEMORY +
+ @discussion +*/ + +extern HRESULT +FFReleaseDevice( + FFDeviceObjectReference deviceReference + ); + + +/*! @function FFIsForceFeedback + @abstract Used to determine if a particular device provided by HID Manager is a force feedback device. + @param hidDevice Pointer to a HID device object to be tested for force feedback support. + @result If the method succeeds, and the device supports FF, the return value is FF_OK. If the method succeeds, and the device does not support FF, the return value is FFERR_NOINTERFACE. If the method fails, the return value is FFERR_INVALIDPARAM + @discussion When you are finished with the device, FFReleaseDevice must be called on the reference received in this function to dispose of the API device object. +*/ + +extern HRESULT +FFIsForceFeedback( + io_service_t hidDevice + ); + + +//----------------------------------------------------------------------------- +// FFDevice (device related) function prototypes +//----------------------------------------------------------------------------- + +/*! @function FFDeviceCreateEffect + @abstract Creates and initializes an instance of an effect identified by the effect UUID on the device. + @param deviceReference An opaque reference handle to a device object. This is obtained from a previous call to FFCreateDevice. + @param uuidRef Reference to the UUID identifying the effect to be created. Only predefined effect UUIDs are accepted. The following standard effect UUIDs are defined: +
+
kFFEffectType_ConstantForce_ID +
kFFEffectType_RampForce_ID +
kFFEffectType_Square_ID +
kFFEffectType_Sine_ID +
kFFEffectType_Triangle_ID +
kFFEffectType_SawtoothUp_ID +
kFFEffectType_SawtoothDown_ID +
kFFEffectType_Spring_ID +
kFFEffectType_Damper_ID +
kFFEffectType_Inertia_ID +
kFFEffectType_Friction_ID +
kFFEffectType_CustomForce_ID +
+
+ @param pEffectDefinition Pointer to FFEFFECT structure that provides parameters for the created effect. This parameter is optional. If it is NULL, the effect object is created without parameters. The application must then call the FFEffectSetParameters function to set the parameters of the effect before it can download the effect. + @param pEffectReference Address of a variable to receive an opaque reference handle to a new effect object. This reference can be used in subsequent calls to FFEffect* functions. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_UNSUPPORTEDAXIS +
FFERR_OUTOFMEMORY +
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_INVALIDDOWNLOADID +
FFERR_INTERNAL +
FFERR_EFFECTTYPEMISMATCH +
+ @discussion When you are finished with the effect, FFReleaseEffect must be called on the reference received in this function to dispose of the API effect object. +*/ + +extern HRESULT +FFDeviceCreateEffect( + FFDeviceObjectReference deviceReference, + CFUUIDRef uuidRef, + FFEFFECT * pEffectDefinition, + FFEffectObjectReference * pEffectReference + ); + + +/*! @function FFDeviceReleaseEffect + @abstract Disposes of an API effect object created with FFDeviceCreateEffect. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @param effectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
FFERR_GENERIC +
FFERR_INTERNAL +
FFERR_INVALIDDOWNLOADID +
+ @discussion +*/ + +extern HRESULT +FFDeviceReleaseEffect( + FFDeviceObjectReference deviceReference, + FFEffectObjectReference effectReference + ); + +/*! @function FFDeviceEscape + @abstract Sends a hardware-specific command to the device. + @param deviceReference An opaque reference handle to a device object. This is obtained from a previous call to FFCreateDevice. + @param pFFEffectEscape Pointer to FFEFFESCAPE structure that describes the command to be sent. On success, the cbOutBuffer member contains the number of bytes of the output buffer used. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_UNSUPPORTED +
+ @discussion Because each driver implements different escapes, it is the application's responsibility to ensure that it is sending the escape to the correct driver. +*/ +extern HRESULT +FFDeviceEscape( + FFDeviceObjectReference deviceReference, + FFEFFESCAPE * pFFEffectEscape + ); + +/*! @function FFDeviceGetForceFeedbackState + @abstract Retrieves the state of the device's force feedback system. + @param deviceReference An opaque reference handle to a device object. This is obtained from a previous call to FFCreateDevice. + @param pFFState Location for flags that describe the current state of the device's force feedback system. +The value is a combination of the following constants: +
+
FFGFFS_ACTUATORSOFF +
The device's force feedback actuators are disabled. +
+
FFGFFS_ACTUATORSON +
The device's force feedback actuators are enabled. +
+
FFGFFS_DEVICELOST +
The device suffered an unexpected failure and is in an indeterminate state. It must be reset either by unacquiring and reacquiring the device, or by sending a FFSFFC_RESET command. +
+
FFGFFS_EMPTY +
The device has no downloaded effects. +
+
FFGFFS_PAUSED +
Playback of all active effects has been paused. +
+
FFGFFS_POWEROFF +
The force feedback system is not currently available. If the device cannot report the power state, neither FFGFFS_POWERON nor FFGFFS_POWEROFF is returned. +
+
FFGFFS_POWERON +
Power to the force feedback system is currently available. If the device cannot report the power state, neither FFGFFS_POWERON nor FFGFFS_POWEROFF is returned. +
+
FFGFFS_SAFETYSWITCHOFF +
The safety switch is currently off; that is, the device cannot operate. If the device cannot report the state of the safety switch, neither FFGFFS_SAFETYSWITCHON nor FFGFFS_SAFETYSWITCHOFF is returned. +
+
FFGFFS_SAFETYSWITCHON +
The safety switch is currently on; that is, the device can operate. If the device cannot report the state of the safety switch, neither FFGFFS_SAFETYSWITCHON nor FFGFFS_SAFETYSWITCHOFF is returned. +
+
FFGFFS_STOPPED +
No effects are playing, and the device is not paused. +
+
FFGFFS_USERFFSWITCHOFF +
The user force feedback switch is currently off; that is, the device cannot operate. If the device cannot report the state of the user force feedback switch, neither FFGFFS_USERFFSWITCHON nor FFGFFS_USERFFSWITCHOFF is returned. +
+
FFGFFS_USERFFSWITCHON +
The user force feedback switch is currently on; that is, the device can operate. If the device cannot report the state of the user force feedback switch, neither FFGFFS_USERFFSWITCHON nor FFGFFS_USERFFSWITCHOFF is returned. +
+
Future versions can define additional flags. Applications should ignore any flags that are not currently defined. +
+ @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
+ @discussion +*/ + +extern HRESULT +FFDeviceGetForceFeedbackState( + FFDeviceObjectReference deviceReference, + FFState * pFFState + ); + +/*! @function FFDeviceSendForceFeedbackCommand + @abstract Sends a command to the device's force feedback system. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @param flags Single value indicating the desired change in state. The value can be one of the following: +
+
FFSFFC_CONTINUE +
Paused playback of all active effects is to be continued. It is an error to send this command when the device is not in a paused state. +
+
FFSFFC_PAUSE +
Playback of all active effects is to be paused. This command also stops the clock-on effects so that they continue playing to their full duration when restarted. +
+
While the device is paused, new effects cannot be started, and existing ones cannot be modified. Doing so can cause the subsequent FFSFFC_CONTINUE command to fail to perform properly. +
+
To abandon a pause and stop all effects, use the FFSFFC_STOPALL or FFSFCC_RESET commands. +
+
FFSFFC_RESET +
The device's force feedback system is to be put in its startup state. All effects are removed from the device, are no longer valid, and must be recreated if they are to be used again. The device's actuators are disabled. +
+
FFSFFC_SETACTUATORSOFF +
The device's force feedback actuators are to be disabled. While the actuators are off, effects continue to play but are ignored by the device. Using the analogy of a sound playback device, they are muted, rather than paused. +
+
FFSFFC_SETACTUATORSON +
The device's force feedback actuators are to be enabled. +
+
FFSFFC_STOPALL +
Playback of any active effects is to be stopped. All active effects are reset, but are still being maintained by the device and are still valid. If the device is in a paused state, that state is lost. +
+
This command is equivalent to calling the FFEffect_Stop method for each effect playing. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_INTERNAL +
+ @discussion +*/ + +extern HRESULT +FFDeviceSendForceFeedbackCommand( + FFDeviceObjectReference deviceReference, + FFCommandFlag flags + ); + +/*! @function FFDeviceSetForceFeedbackProperty + @abstract Retrieves the device's force feedback capabilities. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @param property The following property values are defined for a FF device: +
+
FFPROP_AUTOCENTER +
Specifies whether the actuated FF axes are self-centering. This property controls the device's "default centering spring". +
The pValue member points to a UInt32 can be one of the following values. +
0 - OFF: The device should not automatically center when the user releases the device. An application that uses force feedback should disable autocentering before playing effects. +
1 - ON: The device should automatically center when the user releases the device. +
Not all devices support the autocenter property. +
+
FFPROP_FFGAIN +
Sets the gain for the device. +
The pValue member points to a UInt32 that contains a gain value that is applied to all effects created on the device. The value is an integer in the range from 0 through 10,000, specifying the amount by which effect magnitudes should be scaled for the device. For example, a value of 10,000 indicates that all effect magnitudes are to be taken at face value. A value of 9,000 indicates that all effect magnitudes are to be reduced to 90% of their nominal magnitudes. +
Setting a gain value is useful when an application wants to scale down the strength of all force feedback effects uniformly, based on user preferences. + @param pValue Address of the location where the property value is to be read. SetForceFeedbackProperty will assume that the data is valid, and of the correct type. + @result If the method succeeds, the return value is FF_OK or FFERR_UNSUPPORTED. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
+ @discussion +*/ + +extern HRESULT +FFDeviceSetForceFeedbackProperty( + FFDeviceObjectReference deviceReference, + FFProperty property, + void * pValue + ); + +/*! @function FFDeviceGetForceFeedbackProperty + @abstract Gets properties that define the device behavior. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @param property The following property values are defined for a FF device (see FFDeviceSetForceFeedbackProperty for details): +
+
FFPROP_AUTOCENTER +
FFPROP_FFGAIN +
+ @param pValue Address of the location where the value associated with the property is to be stored. GetForceFeedbackProperty assumes that the pointer is valid, although it will perform a size check before writing the data to pValue + @param valueSize Size, in bytes, of data area pointed to by pValue. Size is compared to expected property size, and the function fails if a mismatch occurs. + @result If the method succeeds, the return value is FF_OK or FFERR_UNSUPPORTED. +If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
+ @discussion +*/ +extern HRESULT +FFDeviceGetForceFeedbackProperty( + FFDeviceObjectReference deviceReference, + FFProperty property, + void * pValue, + IOByteCount valueSize + ); + +/*! @function FFDeviceSetCooperativeLevel + @abstract Function is unimplemented in version 1.0 of this API + @discussion +*/ +extern HRESULT +FFDeviceSetCooperativeLevel( + FFDeviceObjectReference deviceReference, + void * taskIdentifier, + FFCooperativeLevelFlag flags + ); + +/*! @function FFDeviceGetForceFeedbackCapabilities + @abstract Retrieves the device's force feedback capabilities. + @param deviceReference An opaque reference handle to the device object that is be disposed of. This handle is obtained from a previous call to FFCreateDevice. + @param pFFCapabilities Pointer to a FFCAPABILITIES structure that is to be filled in by the this call. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
+ @discussion +*/ + +extern HRESULT +FFDeviceGetForceFeedbackCapabilities( + FFDeviceObjectReference deviceReference, + FFCAPABILITIES * pFFCapabilities + ); + + +//----------------------------------------------------------------------------- +// FFEffect (effect related) function prototypes +//----------------------------------------------------------------------------- + +/*! @function FFEffectDownload + @abstract Places the effect on the device. If the effect is already on the device, the existing effect is updated to match the values set by the FFEffectSetParameters method. + @param efffectRef An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @result If the method succeeds, the return value is FF_OK or S_FALSE. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_INVALIDDOWNLOADID +
FFERR_INTERNAL +
FFERR_EFFECTTYPEMISMATCH +
+
If the method returns S_FALSE, the effect has already been downloaded to the device. +
+ @discussion It is valid to update an effect while it is playing. The semantics of such an operation are explained in the reference for FFEffectSetParameters. +*/ + +extern HRESULT +FFEffectDownload( + FFEffectObjectReference effectReference + ); + +/*! @function FFEffectEscape + @abstract Sends a hardware-specific command to the driver. + @param effectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @param pFFEffectEscape FFEFFESCAPE structure that describes the command to be sent. On success, the cbOutBuffer member contains the number of bytes of the output buffer used. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
FFERR_UNSUPPORTED +
+
Other device-specific error codes are also possible. Ask the hardware manufacturer for details +
+ @discussion Because each driver implements different escapes, it is the application's responsibility to ensure that it is sending the escape to the correct driver. +*/ + +extern HRESULT +FFEffectEscape( + FFEffectObjectReference effectReference, + FFEFFESCAPE * pFFEffectEscape + ); + +/*! @function FFEffectGetEffectStatus + @abstract Sends a hardware-specific command to the driver. + @param effectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @param pFlags Pointer to status flags for the effect. The value can be 0 or one or more of the following constants: +
+
FFEGES_PLAYING +
The effect is playing. +
+
FFEGES_EMULATED +
The effect is emulated. +
+ @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
+ @discussion +*/ + +extern HRESULT +FFEffectGetEffectStatus( + FFEffectObjectReference effectReference, + FFEffectStatusFlag * pFlags + ); + +/*! @function FFEffectGetParameters + @abstract Retrieves information about an effect. + @param efffectRef An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @param pFFEffect Address of a FFEFFECT structure that receives effect information. The dwSize member must be filled in by the application before calling this method. + @param flags Flags that specify which parts of the effect information are to be retrieved. The value can be 0 or one or more of the following constants: +
+
FFEP_ALLPARAMS +
The union of all other FFEP_* flags, indicating that all members of the FFEFFECT structure are being requested. +
+
FFEP_AXES +
The cAxes and rgdwAxes members should receive data. The cAxes member on entry contains the size (in DWORDs) of the buffer pointed to by the rgdwAxes member. If the buffer is too small, the method returns FFERR_MOREDATA and sets cAxes to the necessary size of the buffer. +
+
FFEP_DIRECTION +
The cAxes and rglDirection members should receive data. The cAxes member on entry contains the size (in DWORDs) of the buffer pointed to by the rglDirection member. If the buffer is too small, the GetParameters method returns FFERR_MOREDATA and sets cAxes to the necessary size of the buffer. +
The dwFlags member must include at least one of the coordinate system flags (FFEFF_CARTESIAN, FFEFF_POLAR, or FFEFF_SPHERICAL). The API returns the direction of the effect in one of the coordinate systems you specified, converting between coordinate systems as necessary. On exit, exactly one of the coordinate system flags is set in the dwFlags member, indicating which coordinate system the FF API used. In particular, passing all three coordinate system flags retrieves the coordinates in exactly the same format in which they were set. +
+
FFEP_DURATION +
The dwDuration member should receive data. +
+
FFEP_ENVELOPE +
The lpEnvelope member points to a FFENVELOPE structure that should receive data. If the effect does not have an envelope associated with it, the lpEnvelope member is set to NULL. +
+
FFEP_GAIN +
The dwGain member should receive data. +
+
FFEP_SAMPLEPERIOD +
The dwSamplePeriod member should receive data. +
+
FFEP_STARTDELAY +
The dwStartDelay member should receive data. +
+
FFEP_TRIGGERBUTTON +
The dwTriggerButton member should receive data. +
+
FFEP_TRIGGERREPEATINTERVAL +
The dwTriggerRepeatInterval member should receive data. +
+
FFEP_TYPESPECIFICPARAMS +
The lpvTypeSpecificParams member points to a buffer whose size is specified by the cbTypeSpecificParams member. On return, the buffer is filled in with the type-specific data associated with the effect, and the cbTypeSpecificParams member contains the number of bytes copied. If the buffer supplied by the application is too small to contain all the type-specific data, the method returns FFERR_MOREDATA, and the cbTypeSpecificParams member contains the required size of the buffer in bytes. +
+ @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
FFERR_MOREDATA +
+ @discussion Common errors resulting in a FFERR_INVALIDPARAM error include not setting the dwSize member of the FFEFFECT structure, passing invalid flags, or not setting up the members in the FFEFFECT structure properly in preparation for receiving the effect information. +*/ + +extern HRESULT +FFEffectGetParameters( + FFEffectObjectReference effectReference, + FFEFFECT * pFFEffect, + FFEffectParameterFlag flags + ); + +/*! @function FFEffectSetParameters + @abstract Sets the characteristics of an effect. + @param efffectRef An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @param pFFEffect Address of a FFEFFECT structure that contains effect information. The dwSize member must be filled in by the application before calling this method, as well as any members specified by corresponding bits in the flags parameter. + @param flags Flags that specify which portions of the effect information are to be set and how the downloading of the parameters should be handled. The value can be 0 or one or more of the following constants: +
+
FFEP_AXES +
The cAxes and rgdwAxes members contain data. +
+
FFEP_DIRECTION +
The cAxes and rglDirection members contain data. The dwFlags member specifies (with FFEFF_CARTESIAN or FFEFF_POLAR) the coordinate system in which the values should be interpreted. +
+
FFEP_DURATION +
The dwDuration member contains data. +
+
FFEP_ENVELOPE +
The lpEnvelope member points to a FFENVELOPE structure that contains data. To detach any existing envelope from the effect, pass this flag and set the lpEnvelope member to NULL. +
+
FFEP_GAIN +
The dwGain member contains data. +
+
FFEP_NODOWNLOAD +
Suppress the automatic FFEffect_Download that is normally performed after the parameters are updated. +
+
FFEP_NORESTART +
Suppress the stopping and restarting of the effect to change parameters. See Remarks. +
+
FFEP_SAMPLEPERIOD +
The dwSamplePeriod member contains data. +
+
FFEP_START +
The effect is to be started (or restarted if it is currently playing) after the parameters are updated. By default, the play state of the effect is not altered. +
+
FFEP_STARTDELAY +
The dwStartDelay member contains data. +
+
FFEP_TRIGGERBUTTON +
The dwTriggerButton member contains data. +
+
+
The dwTriggerRepeatInterval member contains data. +
+
FFEP_TYPESPECIFICPARAMS +
The lpvTypeSpecificParams and cbTypeSpecificParams members of the FFEFFECT structure contain the address and size of type-specific data for the effect. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_UNSUPPORTEDAXIS +
FFERR_OUTOFMEMORY +
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_INVALIDDOWNLOADID +
FFERR_INTERNAL +
FFERR_EFFECTTYPEMISMATCH +
+ @discussion The FFEffectSetParameters method automatically downloads the effect, but this behavior can be suppressed by setting the FFEP_NODOWNLOAD flag. If automatic download has been suppressed, you can manually download the effect by invoking the FFEffectDownload method. +
+
If the effect is playing while the parameters are changed, the new parameters take effect as if they were the parameters when the effect started. +
+
For example, suppose a periodic effect with a duration of three seconds is started. After two seconds, the direction of the effect is changed. The effect then continues for one additional second in the new direction. The envelope, phase, amplitude, and other parameters of the effect continue smoothly, as if the direction had not changed. +
+
In the same situation, if after two seconds the duration of the effect were changed to 1.5 seconds, the effect would stop. +
+
Normally, if the driver cannot update the parameters of a playing effect, the driver is permitted to stop the effect, update the parameters, and then restart the effect. Passing the FFEP_NORESTART flag suppresses this behavior. If the driver cannot update the parameters of an effect while it is playing, the error code FFERR_EFFECTPLAYING is returned, and the parameters are not updated. +
+
No more than one of the FFEP_NODOWNLOAD, FFEP_START, and FFEP_NORESTART flags should be set. (It is also valid to pass none of them.) +
+
These three flags control download and playback behavior as follows: +
+
If FFEP_NODOWNLOAD is set, the effect parameters are updated but not downloaded to the device. +
+
If the FFEP_START flag is set, the effect parameters are updated and downloaded to the device, and the effect is started just as if the FFEffect_Start method had been called with the dwIterations parameter set to 1 and with no flags. (Combining the update with FFEP_START is slightly faster than calling Start separately, because it requires less information to be transmitted to the device.) +
+
If neither FFEP_NODOWNLOAD nor FFEP_START is set and the effect is not playing, the parameters are updated and downloaded to the device. +
+
If neither FFEP_NODOWNLOAD nor FFEP_START is set and the effect is playing, the parameters are updated if the device supports on-the-fly updating. Otherwise the behavior depends on the state of the FFEP_NORESTART flag. If it is set, the error code FFERR_EFFECTPLAYING is returned. If it is clear, the effect is stopped, the parameters are updated, and the effect is restarted. + +*/ + +extern HRESULT +FFEffectSetParameters( + FFEffectObjectReference effectReference, + FFEFFECT * pFFEffect, + FFEffectParameterFlag flags + ); + +/*! @function FFEffectStart + @abstract Begins playing an effect. If the effect is already playing, it is restarted from the beginning. If the effect has not been downloaded or has been modified since its last download, it is downloaded before being started. This default behavior can be suppressed by passing the FFES_NODOWNLOAD flag. + @param efffectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @param iterations Number of times to play the effect in sequence. The envelope is re-articulated with each iteration. +
+
To play the effect exactly once, pass 1. To play the effect repeatedly until explicitly stopped, pass INFINITE. To play the effect until explicitly stopped without re-articulating the envelope, modify the effect parameters with the FFEffect_SetParameters method, and change the dwDuration member to INFINITE. + @param flags Flags that describe how the effect should be played by the device. The value can be 0 or one or more of the following values: +
+
FFES_SOLO +
All other effects on the device should be stopped before the specified effect is played. If this flag is omitted, the effect is mixed with existing effects already started on the device. +
+
FFES_NODOWNLOAD +
Do not automatically download the effect. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_INVALIDDOWNLOADID +
FFERR_INTERNAL +
FFERR_EFFECTTYPEMISMATCH +
FFERR_GENERIC +
+ @discussion Not all devices support multiple iterations. +*/ + +extern HRESULT +FFEffectStart( + FFEffectObjectReference effectReference, + UInt32 iterations, + FFEffectStartFlag flags + ); + +/*! @function FFEffectStop + @abstract Stops playing an effect. + @param effectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
FFERR_GENERIC +
FFERR_INTERNAL +
FFERR_INVALIDDOWNLOADID +
+ @discussion +*/ + +extern HRESULT +FFEffectStop( + FFEffectObjectReference effectReference + ); + +/*! @function FFEffectUnload + @abstract Removes the effect from the device. If the effect is playing, it is automatically stopped before it is unloaded. + @param effectReference An opaque reference handle to an effect object. This is obtained from a previous call to FFDeviceCreateEffect. + @result If the method succeeds, the return value is FF_OK. If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
FFERR_NOTDOWNLOADED +
FFERR_GENERIC +
FFERR_INTERNAL +
FFERR_INVALIDDOWNLOADID +
+ @discussion +*/ +extern HRESULT +FFEffectUnload( + FFEffectObjectReference effectReference + ); + + +#ifdef __cplusplus +} +#endif + +#endif // _FORCEFEEDBACK_H_ + + + + + + + diff --git a/Frameworks/ForceFeedback.framework/Versions/Current/Headers/ForceFeedbackConstants.h b/Frameworks/ForceFeedback.framework/Versions/Current/Headers/ForceFeedbackConstants.h new file mode 100755 index 0000000..30e5222 --- /dev/null +++ b/Frameworks/ForceFeedback.framework/Versions/Current/Headers/ForceFeedbackConstants.h @@ -0,0 +1,572 @@ +//----------------------------------------------------------------------------- +// File: ForceFeedbackConstants.h +// Contains: Public interfaces for ForceFeedback technology. +// Copyright: © 2002 by Apple Computer, Inc. All rights reserved. +// +//----------------------------------------------------------------------------- + +#ifndef _FORCEFEEDBACKCONSTANTS_H_ +#define _FORCEFEEDBACKCONSTANTS_H_ + +#if PRAGMA_ONCE +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! @header ForceFeedbackConstants.h + @abstract Constants used in the public interfaces to the Force Feedback implementation in Mac OS X. + @discussion This header file contains the Effect type UUIDs, type definitions used in the API, force feedback + constants and error values used by the API. + +*/ + +//----------------------------------------------------------------------------- +// General defines +//----------------------------------------------------------------------------- +#if !defined( DWORD ) +typedef UInt32 DWORD; +typedef DWORD* LPDWORD; +#endif +#if !defined( LONG ) +typedef SInt32 LONG; +typedef LONG* LPLONG; +#endif + +#define FF_INFINITE 0xFFFFFFFF + +#define FF_DEGREES 100 +#define FF_FFNOMINALMAX 10000 +#define FF_SECONDS 1000000 + + +//----------------------------------------------------------------------------- +// Effect type UUIDs +//----------------------------------------------------------------------------- + +// E559C460-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_ConstantForce_ID + @discussion UUID for a constant force effect type + */ +#define kFFEffectType_ConstantForce_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x60, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C461-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_RampForce_ID + @discussion UUID for a ramp force effect type + */ +#define kFFEffectType_RampForce_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x61, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C462-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Square_ID + @discussion UUID for a square wave effect type + */ +#define kFFEffectType_Square_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x62, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C463-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Sine_ID + @discussion UUID for a sine wave effect type + */ +#define kFFEffectType_Sine_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x63, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C464-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Sine_ID + @discussion UUID for a sine wave effect type + */ +#define kFFEffectType_Triangle_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x64, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C465-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_SawtoothUp_ID + @discussion UUID for a upwards sawtooth wave effect type + */ +#define kFFEffectType_SawtoothUp_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x65, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C466-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_SawtoothDown_ID + @discussion UUID for a downwards sawtooth wave effect type + */ +#define kFFEffectType_SawtoothDown_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x66, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C467-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Spring_ID + @discussion UUID for a spring effect type + */ +#define kFFEffectType_Spring_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x67, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C468-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Damper_ID + @discussion UUID for a damper effect type + */ +#define kFFEffectType_Damper_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x68, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C469-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Inertia_ID + @discussion UUID for an inertia effect type + */ +#define kFFEffectType_Inertia_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x69, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C46A-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_Friction_ID + @discussion UUID for a friction effect type + */ +#define kFFEffectType_Friction_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x6A, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +// E559C46B-C5CD-11D6-8A1C-00039353BD00 +/*! + @defined kFFEffectType_CustomForce_ID + @discussion UUID for a custom force effect type + */ +#define kFFEffectType_CustomForce_ID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xE5, 0x59, 0xC4, 0x6B, 0xC5, 0xCD, 0x11, 0xD6, \ + 0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00) + +//----------------------------------------------------------------------------- +// Effect definition constants +//----------------------------------------------------------------------------- + +// FFEFFECT.dwFlags constants +// IMPORTANT NOTE: OBJECT IDS cannot be used to identify trigger buttons +// in FFEFFECT.dwTriggerButton, and output axes in FFEFFECT.rgdwAxes[n]. +// Please use object offsets (FFJOFS_* constants), the only supported method. +// #define FFEFF_OBJECTIDS 0x00000001 +#define FFEFF_OBJECTOFFSETS 0x00000002 + +typedef UInt32 FFCoordinateSystemFlag; +enum +{ + FFEFF_CARTESIAN = 0x00000010, + FFEFF_POLAR = 0x00000020, + FFEFF_SPHERICAL = 0x00000040 +}; + +// Effect Parameter flags for use in calls to FFEffectGetParameters() and FFEffectSetParameters() +// +typedef UInt32 FFEffectParameterFlag; +enum +{ + FFEP_DURATION = 0x00000001, + FFEP_SAMPLEPERIOD = 0x00000002, + FFEP_GAIN = 0x00000004, + FFEP_TRIGGERBUTTON = 0x00000008, + FFEP_TRIGGERREPEATINTERVAL = 0x00000010, + FFEP_AXES = 0x00000020, + FFEP_DIRECTION = 0x00000040, + FFEP_ENVELOPE = 0x00000080, + FFEP_TYPESPECIFICPARAMS = 0x00000100, + FFEP_STARTDELAY = 0x00000200, + FFEP_ALLPARAMS = 0x000003FF, + FFEP_START = 0x20000000, + FFEP_NORESTART = 0x40000000, + FFEP_NODOWNLOAD = 0x80000000, + FFEB_NOTRIGGER = 0xFFFFFFFF +}; + +// Effect Parameter flags for use in calls to FFEffectStart() +// +typedef UInt32 FFEffectStartFlag; +enum +{ + FFES_SOLO = 0x00000001, + FFES_NODOWNLOAD = 0x80000000 +}; + +// Effect Parameter flags for use in calls to FFEffectGetEffectStatus() +// +typedef UInt32 FFEffectStatusFlag; +enum +{ + FFEGES_NOTPLAYING = 0x00000000, + FFEGES_PLAYING = 0x00000001, + FFEGES_EMULATED = 0x00000002 +}; + +// command flags for FFDeviceSendForceFeedbackCommand() +// +typedef UInt32 FFCommandFlag; +enum +{ + FFSFFC_RESET = 0x00000001, + FFSFFC_STOPALL = 0x00000002, + FFSFFC_PAUSE = 0x00000004, + FFSFFC_CONTINUE = 0x00000008, + FFSFFC_SETACTUATORSON = 0x00000010, + FFSFFC_SETACTUATORSOFF = 0x00000020 +}; + +// device state flags returned by FFDeviceGetForceFeedbackState() +// +typedef UInt32 FFState; +enum +{ + FFGFFS_EMPTY = 0x00000001, + FFGFFS_STOPPED = 0x00000002, + FFGFFS_PAUSED = 0x00000004, + FFGFFS_ACTUATORSON = 0x00000010, + FFGFFS_ACTUATORSOFF = 0x00000020, + FFGFFS_POWERON = 0x00000040, + FFGFFS_POWEROFF = 0x00000080, + FFGFFS_SAFETYSWITCHON = 0x00000100, + FFGFFS_SAFETYSWITCHOFF = 0x00000200, + FFGFFS_USERFFSWITCHON = 0x00000400, + FFGFFS_USERFFSWITCHOFF = 0x00000800, + FFGFFS_DEVICELOST = 0x80000000 +}; + + +// axis and button "field offsets", +// used in +// FFEFFECT.dwTriggerButton +// FFEFFECT.rgdwAxes[n] +#define FFJOFS_X 0 +#define FFJOFS_Y 4 +#define FFJOFS_Z 8 +#define FFJOFS_RX 12 +#define FFJOFS_RY 16 +#define FFJOFS_RZ 20 +#define FFJOFS_SLIDER(n) (24 + (n) * sizeof(LONG)) +#define FFJOFS_POV(n) (32 + (n) * sizeof(DWORD)) +#define FFJOFS_BUTTON(n) (48 + (n)) +#define FFJOFS_BUTTON0 FFJOFS_BUTTON(0) +#define FFJOFS_BUTTON1 FFJOFS_BUTTON(1) +#define FFJOFS_BUTTON2 FFJOFS_BUTTON(2) +#define FFJOFS_BUTTON3 FFJOFS_BUTTON(3) +#define FFJOFS_BUTTON4 FFJOFS_BUTTON(4) +#define FFJOFS_BUTTON5 FFJOFS_BUTTON(5) +#define FFJOFS_BUTTON6 FFJOFS_BUTTON(6) +#define FFJOFS_BUTTON7 FFJOFS_BUTTON(7) +#define FFJOFS_BUTTON8 FFJOFS_BUTTON(8) +#define FFJOFS_BUTTON9 FFJOFS_BUTTON(9) +#define FFJOFS_BUTTON10 FFJOFS_BUTTON(10) +#define FFJOFS_BUTTON11 FFJOFS_BUTTON(11) +#define FFJOFS_BUTTON12 FFJOFS_BUTTON(12) +#define FFJOFS_BUTTON13 FFJOFS_BUTTON(13) +#define FFJOFS_BUTTON14 FFJOFS_BUTTON(14) +#define FFJOFS_BUTTON15 FFJOFS_BUTTON(15) +#define FFJOFS_BUTTON16 FFJOFS_BUTTON(16) +#define FFJOFS_BUTTON17 FFJOFS_BUTTON(17) +#define FFJOFS_BUTTON18 FFJOFS_BUTTON(18) +#define FFJOFS_BUTTON19 FFJOFS_BUTTON(19) +#define FFJOFS_BUTTON20 FFJOFS_BUTTON(20) +#define FFJOFS_BUTTON21 FFJOFS_BUTTON(21) +#define FFJOFS_BUTTON22 FFJOFS_BUTTON(22) +#define FFJOFS_BUTTON23 FFJOFS_BUTTON(23) +#define FFJOFS_BUTTON24 FFJOFS_BUTTON(24) +#define FFJOFS_BUTTON25 FFJOFS_BUTTON(25) +#define FFJOFS_BUTTON26 FFJOFS_BUTTON(26) +#define FFJOFS_BUTTON27 FFJOFS_BUTTON(27) +#define FFJOFS_BUTTON28 FFJOFS_BUTTON(28) +#define FFJOFS_BUTTON29 FFJOFS_BUTTON(29) +#define FFJOFS_BUTTON30 FFJOFS_BUTTON(30) +#define FFJOFS_BUTTON31 FFJOFS_BUTTON(31) + +// defines for FFDeviceGetForceFeedbackProperty() and FFDeviceSetForceFeedbackProperty() +// +typedef UInt32 FFProperty; +enum +{ + FFPROP_FFGAIN = 1, + FFPROP_AUTOCENTER = 3 +}; + +// flags for FFDeviceSetCooperativeLevel() +// +typedef UInt32 FFCooperativeLevelFlag; +enum +{ + FFSCL_EXCLUSIVE = 0x00000001, + FFSCL_NONEXCLUSIVE = 0x00000002, + FFSCL_FOREGROUND = 0x00000004, + FFSCL_BACKGROUND = 0x00000008 +}; + +// types used in FFCAPABILITIES structure +// +typedef UInt32 FFCapabilitiesEffectType; +enum +{ + FFCAP_ET_CONSTANTFORCE = 0x00000001, + FFCAP_ET_RAMPFORCE = 0x00000002, + FFCAP_ET_SQUARE = 0x00000004, + FFCAP_ET_SINE = 0x00000008, + FFCAP_ET_TRIANGLE = 0x00000010, + FFCAP_ET_SAWTOOTHUP = 0x00000020, + FFCAP_ET_SAWTOOTHDOWN = 0x00000040, + FFCAP_ET_SPRING = 0x00000080, + FFCAP_ET_DAMPER = 0x00000100, + FFCAP_ET_INERTIA = 0x00000200, + FFCAP_ET_FRICTION = 0x00000400, + FFCAP_ET_CUSTOMFORCE = 0x00000800 +}; + +typedef UInt32 FFCapabilitiesEffectSubType; +enum +{ + FFCAP_ST_KINESTHETIC = 1, + FFCAP_ST_VIBRATION = 2 +}; + + +//----------------------------------------------------------------------------- +// Error return values +//----------------------------------------------------------------------------- + +/*! + @defined FF_OK + @discussion The operation completed successfully. +*/ +#define FF_OK S_OK + +/*! + @defined FF_FALSE + @discussion The operation did not complete successfully. +*/ +#define FF_FALSE S_FALSE + +/*! + @defined FF_DOWNLOADSKIPPED + * @discussion + * The parameters of the effect were successfully updated by + * FFEffectSetParameters, but the effect was not + * downloaded because the FFEP_NODOWNLOAD flag was passed. + */ +#define FF_DOWNLOADSKIPPED ((HRESULT)0x00000003L) + +/*! + @defined FF_EFFECTRESTARTED + * @discussion + * The parameters of the effect were successfully updated by + * FFEffectSetParameters, but in order to change + * the parameters, the effect needed to be restarted. + */ +#define FF_EFFECTRESTARTED ((HRESULT)0x00000004L) + +/*! + @defined FF_TRUNCATED + * @discussion + * The parameters of the effect were successfully updated by + * FFEffectSetParameters, but some of them were + * beyond the capabilities of the device and were truncated. + */ +#define FF_TRUNCATED ((HRESULT)0x00000008L) + +/*! + @defined FF_TRUNCATEDANDRESTARTED + * @discussion + * Equal to FF_EFFECTRESTARTED | FF_TRUNCATED. + */ +#define FF_TRUNCATEDANDRESTARTED ((HRESULT)0x0000000CL) + +/*! + @defined FFERR_DEVICENOTREG + * @discussion + * The device or device instance or effect is not registered. + */ +#define FFERR_DEVICENOTREG REGDB_E_CLASSNOTREG + +/*! + @defined FFERR_INVALIDPARAM + * @discussion + * An invalid parameter was passed to the returning function, + * or the object was not in a state that admitted the function + * to be called. + */ +#define FFERR_INVALIDPARAM E_INVALIDARG + +/*! + @defined FFERR_NOINTERFACE + * @discussion + * The specified interface is not supported by the object + */ +#define FFERR_NOINTERFACE E_NOINTERFACE + +/*! + @defined FFERR_GENERIC + * @discussion + * An undetermined error occurred. + */ +#define FFERR_GENERIC E_FAIL + +/*! + @defined FFERR_OUTOFMEMORY + * @discussion + * Couldn't allocate sufficient memory to complete the caller's request. + */ +#define FFERR_OUTOFMEMORY E_OUTOFMEMORY + +/*! + @defined FFERR_UNSUPPORTED + * @discussion + * The function called is not supported at this time + */ +#define FFERR_UNSUPPORTED E_NOTIMPL + +#ifndef E_PENDING +/*! + @defined E_PENDING + * @discussion + * Data is not yet available. + */ +#define E_PENDING 0x8000000AL +#endif + +/*! + @defined FFERR_DEVICEFULL + * @discussion + * The device is full. + */ +#define FFERR_DEVICEFULL 0x80040201L + +/*! + @defined FFERR_MOREDATA + * @discussion + * Not all the requested information fit into the buffer. + */ +#define FFERR_MOREDATA 0x80040202L + +/*! + @defined FFERR_NOTDOWNLOADED + * @discussion + * The effect is not downloaded. + */ +#define FFERR_NOTDOWNLOADED 0x80040203L + +/*! + @defined FFERR_HASEFFECTS + * @discussion + * The device cannot be reinitialized because there are still effects + * attached to it. + */ +#define FFERR_HASEFFECTS 0x80040204L + +/*! + @defined FFERR_INCOMPLETEEFFECT + * @discussion + * The effect could not be downloaded because essential information + * is missing. For example, no axes have been associated with the + * effect, or no type-specific information has been created. + */ +#define FFERR_INCOMPLETEEFFECT 0x80040206L + +/*! + @defined FFERR_EFFECTPLAYING + * @discussion + * An attempt was made to modify parameters of an effect while it is + * playing. Not all hardware devices support altering the parameters + * of an effect while it is playing. + */ +#define FFERR_EFFECTPLAYING 0x80040208L + +/*! + @defined FFERR_UNPLUGGED + * @discussion + * The operation could not be completed because the device is not + * plugged in. + */ +#define FFERR_UNPLUGGED 0x80040209L + + +// +// Mac OS X specific +// + +/*! + @defined FFERR_INVALIDDOWNLOADID + * @discussion + * The effect index provided by the API in downloadID is not recognized by the + * IOForceFeedbackLib driver. + */ +#define FFERR_INVALIDDOWNLOADID 0x80040300 + +/*! + @defined FFERR_DEVICEPAUSED + * @discussion + * When the device is paused via a call to FFDeviceSendForceFeedbackCommand(), + * other operations such as modifying existing effect parameters and creating + * new effects are not allowed. + */ +#define FFERR_DEVICEPAUSED 0x80040301 + +/*! + @defined FFERR_INTERNAL + * @discussion + * The IOForceFededbackLib driver has detected an internal fault. Often this + * occurs because of an unexpected internal code path. + */ +#define FFERR_INTERNAL 0x80040302 + +/*! + @defined FFERR_EFFECTTYPEMISMATCH + * @discussion + * The IOForceFededbackLib driver has received an effect modification request + * whose basic type does not match the defined effect type for the given effect. + */ +#define FFERR_EFFECTTYPEMISMATCH 0x80040303 + +/*! + @defined FFERR_UNSUPPORTEDAXIS + * @discussion + * The effect includes one or more axes that the device does not support. + */ +#define FFERR_UNSUPPORTEDAXIS 0x80040304 + +/*! + @defined FFERR_NOTINITIALIZED + * @discussion + * This object has not been initialized + */ +#define FFERR_NOTINITIALIZED 0x80040305 + +/*! + @defined FFERR_EFFECTTYPENOTSUPPORTED + * @discussion + * The effect type requested is not explicitly supported by the particular device. + */ +#define FFERR_EFFECTTYPENOTSUPPORTED 0x80040306 + +/*! + @defined FFERR_DEVICERELEASED + * @discussion + * The device has been released. + */ +#define FFERR_DEVICERELEASED 0x80040307 + +#ifdef __cplusplus +} +#endif + +#endif // _FORCEFEEDBACKCONSTANTS_H_ + diff --git a/Frameworks/ForceFeedback.framework/Versions/Current/Headers/IOForceFeedbackLib.h b/Frameworks/ForceFeedback.framework/Versions/Current/Headers/IOForceFeedbackLib.h new file mode 100755 index 0000000..7bce10c --- /dev/null +++ b/Frameworks/ForceFeedback.framework/Versions/Current/Headers/IOForceFeedbackLib.h @@ -0,0 +1,447 @@ +//----------------------------------------------------------------------------- +// File: IOForceFeedbackLib.h +// Contains: Public interfaces for the Force Feedback Plugin architecture . +// Copyright: © 2002 by Apple Computer, Inc. All rights reserved. +// +//----------------------------------------------------------------------------- + +#ifndef _IOFORCEFEEDBACKLIB_H +#define _IOFORCEFEEDBACKLIB_H + +#if PRAGMA_ONCE +#pragma once +#endif + +/*! @header IOForceFeedbackLib.h + @abstract Public Interfaces and constants used to develop Force Feedback plugIns. + @discussion A force feedback device manufacturer might need to implement a plug in + to allow the Force Feedback Library to control the device. This header + file describes the functions that need to be implemented. This interface definition + follows Microsoft Windoes IDirectInputEffectDriver definition wherever it makes sense to do so. + Certain functions may contain more or fewer parameters than the Windows version + +*/ +#include + +__BEGIN_DECLS +#include +#if COREFOUNDATION_CFPLUGINCOM_SEPARATE +#include +#endif + +#include +#include +#include + +//==================================================================================================================== +// The Version of the FF PlugIn API +//==================================================================================================================== +// +enum { + kFFPlugInAPIMajorRev = 1, + kFFPlugInAPIMinorAndBugRev = 0, + kFFPlugInAPIStage = finalStage, + kFFPlugInAPINonRelRev = 0 +}; + +//==================================================================================================================== +// Defines +//==================================================================================================================== +// + +#define FFDEVICESTATE ForceFeedbackDeviceState +#define PFFDEVICESTATE ForceFeedbackDeviceStatePtr + + +// F4545CE5-BF5B-11D6-A4BB-0003933E3E3E +#define kIOForceFeedbackLibTypeID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0xF4, 0x54, 0x5C, 0xE5, 0xBF, 0x5B, 0x11, 0xD6, \ + 0xA4, 0xBB, 0x00, 0x03, 0x93, 0x3E, 0x3E, 0x3E) + +// 1C7C5850-BB6A-11D6-B75F-003065FBE6B0 +#define kIOForceFeedbackDeviceInterfaceID CFUUIDGetConstantUUIDWithBytes(NULL, \ + 0x1C, 0x7C, 0x58, 0x50, 0xBB, 0x6A, 0x11, 0xD6, \ + 0xB7, 0x5F, 0x00, 0x30, 0x65, 0xFB, 0xE6, 0xB0) + + +//==================================================================================================================== +// Structs +//==================================================================================================================== +// +struct ForceFeedbackDeviceState +{ + UInt32 dwSize; + UInt32 dwState; + UInt32 dwLoad; + +}; + +typedef struct ForceFeedbackDeviceState ForceFeedbackDeviceState; +typedef ForceFeedbackDeviceState * ForceFeedbackDeviceStatePtr; + + +struct ForceFeedbackVersion +{ + NumVersion apiVersion; + NumVersion plugInVersion; +}; + +typedef struct ForceFeedbackVersion ForceFeedbackVersion; +typedef ForceFeedbackVersion * ForceFeedbackVersionPtr; + +//==================================================================================================================== +// Types +//==================================================================================================================== +// +typedef UInt32 FFEffectDownloadID; + + +//==================================================================================================================== +// +// ForceFeedback Device Interface Functions available in version 1.0 of architecture +// +//==================================================================================================================== +// +#define IOFORCEFEEDBACKDEVICE_FUNCS_100 \ + \ + HRESULT (*ForceFeedbackGetVersion)( void * self, \ + ForceFeedbackVersion * version); \ + \ + HRESULT (*InitializeTerminate)( void * self, \ + NumVersion forceFeedbackAPIVersion,\ + io_object_t hidDevice, \ + bool begin ); \ + \ + HRESULT (*DestroyEffect)( void * self, \ + FFEffectDownloadID downloadID ); \ + \ + HRESULT (*DownloadEffect)( void * self, \ + CFUUIDRef effectType, \ + FFEffectDownloadID * pDownloadID, \ + FFEFFECT * pEffect, \ + FFEffectParameterFlag flags ); \ + \ + HRESULT (*Escape)( void * self, \ + FFEffectDownloadID downloadID, \ + FFEFFESCAPE * pEscape ); \ + \ + HRESULT (*GetEffectStatus)( void * self, \ + FFEffectDownloadID downloadID, \ + FFEffectStatusFlag * pStatusCode ); \ + \ + HRESULT (*GetForceFeedbackCapabilities)( void * self, \ + FFCAPABILITIES * pCapabilities ); \ + \ + HRESULT (*GetForceFeedbackState)( void * self, \ + ForceFeedbackDeviceState * pDeviceState ); \ + \ + HRESULT (*SendForceFeedbackCommand)( void * self, \ + FFCommandFlag state ); \ + \ + HRESULT (*SetProperty)( void * self, \ + FFProperty property, \ + void * pValue ); \ + \ + HRESULT (*StartEffect)( void * self, \ + FFEffectDownloadID downloadID, \ + FFEffectStartFlag mode, \ + UInt32 iterations ); \ + \ + HRESULT (*StopEffect)( void * self, \ + FFEffectDownloadID downloadID ); + +//==================================================================================================================== +// +// END OF DeviceInterface Functions available in version 1.0 of this API +// +//==================================================================================================================== +// +struct IOForceFeedbackDeviceInterface { + IUNKNOWN_C_GUTS; + IOFORCEFEEDBACKDEVICE_FUNCS_100 +}; + +typedef struct IOForceFeedbackDeviceInterface IOForceFeedbackDeviceInterface; +typedef IOForceFeedbackDeviceInterface * IOForceFeedbackDeviceInterfacePtr; + + +//==================================================================================================================== +// +// ¥¥¥¥¥ The following is #ifdef out. It is here so that we can header doc this file without intruding in its +// ¥¥¥¥¥ readability. +// +//==================================================================================================================== +// +#if 0 + +struct IOForceFeedbackDeviceInterface { + IUNKNOWN_C_GUTS; + +/*! @function ForceFeedbackGetVersion + @abstract This function is used to determine driver and API version information. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param version Pointer to ForceFeedbackVersion structure that is to receive the required info. See the structure description for details. + @result Returns FF_OK if successful, or an error value otherwise. +*/ + HRESULT (*ForceFeedbackGetVersion) (void * self, ForceFeedbackVersion * version); + + +/*! @function InitializeTerminate + @abstract This function is used to "create and destroy" particular device instances. It provides the FF plug-in driver with all the necessary start-up parameters. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param forceFeedbackAPIVersion The version number of FF API that loaded the effect driver. The plugIn should check that the major version of the forceFeedbackAPI version is the same as the major version of the API at the time the plugIn was compiled. If the major versions are different, then the plugIn API has changed and the plugIn will NOT be compatible with it. +
+If begin is false, this parameter is ignored. + @param hidDevice A device object that can be used by the FF plug-in to establish a connection to and communicate with the device. The caller will release the hidDevice device object with a call to IOObjectRelease() once the FF plug-in completes its InitializeTerminate processing, so a FF plug-in implementation should not make a copy of the io_object_t variable with the intention of using it outside the context of this call. +
+If begin is false, this parameter is ignored. (You can pass NULL.) + @param begin Nonzero if access to the device is beginning. Zero if the access to the device is ending. The FF API will call InitializeTerminate( begin=TRUE) when a FF device is first selected for use, and InitializeTerminate( begin=false) when the FF device is no longer needed. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INVALIDPARAM +
FFERR_NOINTERFACE +
FFERR_OUTOFMEMORY +
+*/ + HRESULT (*InitializeTerminate)(void * self, NumVersion forceFeedbackAPIVersion, io_object_t hidDevice, bool begin ); + + +/*! @function DestroyEffect + @abstract This function commands the device to "destroy" a currently downloaded effect. The effect ID and any data that is associated with the effect are freed and available for reallocation. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param downloadID Indicates the effect ID that was obtained from the device when the effect was downloaded. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INVALIDDOWNLOADID +
FFERR_GENERIC +
FFERR_INTERNAL +
+*/ + HRESULT (*DestroyEffect)(void * self, FFEffectDownloadID downloadID ); + + +/*! @function DownloadEffect + @abstract This function sends an effect to the device. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param effectType Indicates the type of effect being created. Valid UUIDs are listed as kFFEffectType_* constants in the ForceFeedbackConstants.h file. (Supported effect types include Sine, Square, Triangle, SawtoothUp, SawtoothDown, Constant, Spring, Damper, etc.). + @param pDownloadID On entry, this parameter points to the handle of the effect being downloaded. If the parameter points to a zero, then a new effect is downloaded. On exit, the FFEffectDownloadID pointed to by this parameter contains the new effect handle. On failure, the FFEffectDownloadID pointed to by this parameter is set to zero if the effect is lost, or left alone if the effect is still valid with its old parameters. Note that zero is never a valid effect handle. + @param pEffect The new parameters for the effect. +
+IMPORTANT NOTE: Unlike the IDirectInputEffectDriver specification, the axis and button values are NOT converted to object identifiers before they are handed over to the driver. In this case, the only supported method used to assign triggers and output axes is through object offsets, defined by the FFJOFS_* constants. Therefore, if a button is assigned to trigger an effect, FFEFFECT.dwTriggerButton will contain a constant of the form FFJOFS_BUTTONn. Similarly, output axes will be identified in FFEFFECT.rgdwAxes[n] as FFJOFS_X, FFJOFS_Y, etc. + @param flags Specifies which portions of the effect information have changed from the effect already on the device. This information is passed to drivers to allow for the optimization of effect modification. If an effect is being modified, a driver may be able to update the effect in its original position and transmit to the device only the information that has changed. Drivers are not, however, required to implement this optimization. All members of the FFEFFECT structure that are pointed to by the pEffect parameter are valid, and a driver may choose simply to update all parameters of the effect at each download. There may be zero, one, or more of the following: +
+
FFEP_DURATION +
Indicates the dwDuration member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_SAMPLEPERIOD +
Indicates the dwSamplePeriod member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_GAIN +
Indicates the dwGain member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_TRIGGERBUTTON +
Indicates the dwTriggerButton member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_TRIGGERREPEATINTERVAL +
Indicates the dwTriggerRepeatInterval member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_AXES +
Indicates the cAxes and rgdwAxes members of the FFEFFECT structure are being downloaded for the first time or have changed since their last download. +
+
FFEP_DIRECTION +
Indicates the cAxes and rglDirection members of the FFEFFECT structure are being downloaded for the first time or have changed since their last download. (The dwFlags member of the FFEFFECT structure specifies, through FFEFF_CARTESIAN or FFEFF_POLAR, the coordinate system in which the values should be interpreted.) +
+
FFEP_ENVELOPE +
Indicates the lpEnvelope member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. If this flag is set and the lpEnvelope member is a NULL pointer, then the effect is being created with no envelope, or the existing envelope is being deleted. +
+
FFEP_TYPESPECIFICPARAMS +
Indicates the cbTypeSpecificParams and lpTypeSpecificParams members of the FFEFFECT structure are being downloaded for the first time or have changed since their last download. +
+
FFEP_STARTDELAY +
Indicates the dwStartDelay member of the FFEFFECT structure is being downloaded for the first time or has changed since its last download. +
+
FFEP_START +
Indicates that the effect is to be restarted from the beginning after the parameters of the effect have been updated. Note that the FFEP_NODOWNLOAD flag overrides the FFEP_START flag. +
+
FFEP_NORESTART +
If this flag is not specified, the effect device driver is permitted to restart the effect if doing so is necessary to change the specified parameters. Note that the FFEP_NODOWNLOAD and FFEP_START flags override this flag. +
+
FFEP_NODOWNLOAD +
Suppresses the automatic download that is normally performed after the parameters are updated. If this flag is set, the driver should validate parameters without performing an actual download. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_INVALIDDOWNLOADID +
FFERR_INTERNAL +
FFERR_EFFECTTYPEMISMATCH +
+*/ + HRESULT (*DownloadEffect)( void * self, CFUUIDRef effectType, FFEffectDownloadID * pDownloadID, +FFEFFECT * pEffect, FFEffectParameterFlag flags ); + + +/*! @function Escape + @abstract This function escapes to the driver. This method is called in response to an application invoking the FFEffectEscape or FFDeviceEscape methods. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param downloadID Specifies the effect at which the command is directed, or zero if the command is directed at the device itself and not any particular effect. + @param pEscape Pointer to a FFEFFESCAPE structure that describes the command to be sent. On success, the cbOutBuffer member contains the number of output buffer bytes actually used. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_UNSUPPORTED +
+*/ + HRESULT (*Escape)( void * self, FFEffectDownloadID downloadID, FFEFFESCAPE * pEscape ); + + +/*! @function GetEffectStatus + @abstract This function returns the device effect's status. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param downloadID Indicates the effect to be queried. + @param pStatusCode Receives the effect status. The FFEffectStatusFlag pointed to by this parameter should be filled in with one of the following values: +
+
FFEGES_PLAYING +
The effect is still playing. +
+
FFEGES_NOTPLAYING +
The effect is not playing. + @result Returns FF_OK. +*/ + HRESULT (*GetEffectStatus)( void * self, FFEffectDownloadID downloadID, FFEffectStatusFlag * pStatusCode ); + + +/*! @function GetForceFeedbackCapabilities + @abstract This function escapes to the driver. This method is called in response to an application invoking the FFEffectEscape or FFDevicEscape methods. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param pCapabilities Pointer to a FFCAPABILITIES structure that should be filled in with version information describing the hardware, firmware, and driver. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INTERNAL +
FFERR_NOINTERFACE +
+*/ + HRESULT (*GetForceFeedbackCapabilities)( void * self, FFCAPABILITIES * pCapabilities ); + + +/*! @function GetForceFeedbackState + @abstract This function returns the state of the device. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param pDeviceState Pointer to a ForceFeedbackDeviceState structure that receives the device state. FF API sets the dwSize member of the ForceFeedbackDeviceState structure to sizeof(ForceFeedbackDeviceState) before calling this method. + @result Returns FF_OK. +*/ + HRESULT (*GetForceFeedbackState)( void * self, ForceFeedbackDeviceState * pDeviceState ); + + +/*! @function SendForceFeedbackCommand + @abstract This function sends a command to the device. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param state Indicates the command being sent. That command can be one of the following: +
+
FFSFFC_RESET +
Indicates that playback of any active effects should be been stopped and that all effects should be removed from the device. Once the device has been reset, all effects are no longer valid and must be re-created. +
+
FFSFFC_STOPALL +
Indicates that playback of all effects should be stopped. Sending the FFSFFC_STOPALL command is equivalent to invoking the FFEffect_Stop method on all effects that are playing. If the device is in a paused state, the device driver is permitted to lose the paused state. +
+
FFSFFC_PAUSE +
Indicates that playback of all effects should be paused. When effects are paused, time "stops" until the FFSFFC_CONTINUE command is sent. For example, suppose an effect of five seconds' duration is started. After one second, all effects are paused. After two more seconds, all effects are continued. The effect should then play for four additional seconds. While a force-feedback device is paused, starting a new effect or modifying existing ones can cause the paused state to be lost. +
+
FFSFFC_CONTINUE +
Indicates that playback should be resumed at the point at which it was interrupted for those effects that were paused by a previous FFSCFFC_PAUSE command. +
+
FFSFFC_SETACTUATORSON +
Indicates that the device's force-feedback actuators should be enabled. +
+
FFSFFC_SETACTUATORSOFF +
Indicates that the device's force-feedback actuators should be disabled. If successful, force-feedback effects are "muted". Note that time continues to elapse while actuators are off. For example, suppose an effect of five seconds' duration is started. After one second, actuators are turned off. After two more seconds, actuators are turned back on. The effect should then play for two additional seconds. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INTERNAL +
FFERR_INVALIDPARAM +
+*/ + HRESULT (*SendForceFeedbackCommand)( void * self, FFCommandFlag state ); + + +/*! @function SetProperty + @abstract This function sets properties that define the device behavior. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param property The following property values are defined for a FF device: +
+
FFPROP_AUTOCENTER +
Specifies whether the actuated FF axes are self-centering. This property controls the deviceÕs Òdefault centering springÓ. +
The pValue member points to a UInt32 and can be one of the following values. +
+
0 - OFF: The device should not automatically center when the user releases the device. An application that uses force feedback should disable autocentering before playing effects. +
+
1 - ON: The device should automatically center when the user releases the device. +
+
Not all devices support the autocenter property. +
+
FFPROP_FFGAIN +
Sets the gain for the device. +
+
The pValue member points to a UInt32 that contains a gain value that is applied to all effects created on the device. The value is an integer in the range from 0 through 10,000, specifying the amount by which effect magnitudes should be scaled for the device. For example, a value of 10,000 indicates that all effect magnitudes are to be taken at face value. A value of 9,000 indicates that all effect magnitudes are to be reduced to 90% of their nominal magnitudes. +
+
Setting a gain value is useful when an application wants to scale down the strength of all force-feedback effects uniformly, based on user preferences. + @param pValue Address of the location where the property value is to be read. This function will assume that the data is valid, and of the correct type. + @result If the method succeeds, the return value is FF_OK or FFERR_UNSUPPORTED. +If the method fails, the return value can be one of the following error values: +
+
FFERR_INVALIDPARAM +
+*/ + HRESULT (*SetProperty)( void * self, FFProperty property, void * pValue ); + + +/*! @function StartEffect + @abstract This function commands the device to play back an effect that was previously loaded. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param downloadID Indicates the effect to be played. + @param mode Specifies how the effect is to affect other effects. Only the mode listed below can be used; all other modes are reserved. For example, the driver never receives the FFES_NODOWNLOAD flag because it is managed by the FF API and not the PlugIn driver. This parameter can be zero, one, or more of the following flags: +
+
FFES_SOLO +
Indicates that all other effects on the device should be stopped before the specified effect is played. If this flag is omitted, the effect is mixed with existing effects that have already started on the device. + @param iterations Specifies the number of times to perform the effect. If the value is FF_INFINITE, then the effect should be repeated until explicitly stopped or paused. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INTERNAL +
FFERR_DEVICEPAUSED +
FFERR_DEVICEFULL +
FFERR_GENERIC +
FFERR_INVALIDDOWNLOADID +
+*/ + HRESULT (*StartEffect)( void * self, FFEffectDownloadID downloadID, FFEffectStartFlag mode, UInt32 iterations ); + +/*! @function StopEffect + @abstract This function commands the device to stop an effect that was previously started. + @discussion + @param self Pointer to the FFPlugInDriver implementation instance. + @param downloadID Indicates the effect to be stopped. + @result Returns FF_OK if successful, or an error value otherwise: +
+
FFERR_INTERNAL +
FFERR_GENERIC +
FFERR_INVALIDDOWNLOADID +
+*/ + HRESULT (*StopEffect)( void * self, UInt32 downloadID ); +}; + +#endif // #if 0 ¥¥¥ Used for header doc'ing only + +__END_DECLS + +#endif /* ! _IOFORCEFEEDBACKLIB_H */ diff --git a/Frameworks/ForceFeedback.framework/Versions/Current/Resources/Info.plist b/Frameworks/ForceFeedback.framework/Versions/Current/Resources/Info.plist new file mode 100755 index 0000000..ce08864 --- /dev/null +++ b/Frameworks/ForceFeedback.framework/Versions/Current/Resources/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ForceFeedback + CFBundleGetInfoString + 1.0.0, Copyright Apple Computer, Inc. 2002 + CFBundleIdentifier + com.apple.ForceFeedback + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ForceFeedback Framework + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0.0 + + diff --git a/Frameworks/ForceFeedback.framework/Versions/Current/Resources/version.plist b/Frameworks/ForceFeedback.framework/Versions/Current/Resources/version.plist new file mode 100755 index 0000000..69ea4de --- /dev/null +++ b/Frameworks/ForceFeedback.framework/Versions/Current/Resources/version.plist @@ -0,0 +1,18 @@ + + + + + BuildVersion + 70 + CFBundleShortVersionString + 1.0.0 + CFBundleVersion + 1.0.0 + ProjectName + ForceFeedback + ReleaseStatus + Beta + SourceVersion + 1000305 + + diff --git a/HID Utilities/HID_Utilities_External.h b/HID Utilities/HID_Utilities_External.h new file mode 100755 index 0000000..5f8800e --- /dev/null +++ b/HID Utilities/HID_Utilities_External.h @@ -0,0 +1,476 @@ +/* + File: HID_Utilities_External.h + + Contains: Definition of the HID Utilities exported functions + + DRI: George Warner + + Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _HID_Utilities_External_h_ +#define _HID_Utilities_External_h_ + +// ================================== +//includes + +#if TARGET_RT_MAC_CFM + typedef void (*IOHIDCallbackFunction)(void * target, unsigned long result, void* refcon, void * sender); +#else + #include +#endif TARGET_RT_MAC_CFM + +#include + +#if 0 +#include + +#include "PID.h" // NOTE: These are now in +#include "IOHIDPowerUsage.h" // NOTE: These are now in +#endif + +#ifdef __MWERKS__ +#define IOHIDEventStruct void +#endif +// ================================== + +#ifdef __cplusplus +extern "C" { +#endif + +// ================================== +// Device and Element Interfaces + +typedef enum HIDElementTypeMask +{ + kHIDElementTypeInput = 1 << 1, + kHIDElementTypeOutput = 1 << 2, + kHIDElementTypeFeature = 1 << 3, + kHIDElementTypeCollection = 1 << 4, + kHIDElementTypeIO = kHIDElementTypeInput | kHIDElementTypeOutput | kHIDElementTypeFeature, + kHIDElementTypeAll = kHIDElementTypeIO | kHIDElementTypeCollection +}HIDElementTypeMask; + +struct recElement +{ + unsigned long type; // the type defined by IOHIDElementType in IOHIDKeys.h + long usagePage; // usage page from IOUSBHIDParser.h which defines general usage + long usage; // usage within above page from IOUSBHIDParser.h which defines specific usage + void * cookie; // unique value (within device of specific vendorID and productID) which identifies element, will NOT change + long min; // reported min value possible + long max; // reported max value possible + long scaledMin; // reported scaled min value possible + long scaledMax; // reported scaled max value possible + long size; // size in bits of data return from element + unsigned char relative; // are reports relative to last report (deltas) + unsigned char wrapping; // does element wrap around (one value higher than max is min) + unsigned char nonLinear; // are the values reported non-linear relative to element movement + unsigned char preferredState; // does element have a preferred state (such as a button) + unsigned char nullState; // does element have null state + long units; // units value is reported in (not used very often) + long unitExp; // exponent for units (also not used very often) + char name[256]; // name of element (c string) + +// runtime variables + long calMin; // min returned value + long calMax; // max returned value (calibrate call) + long userMin; // user set value to scale to (scale call) + long userMax; + + struct recElement * pPrevious; // previous element (NULL at list head) + struct recElement * pChild; // next child (only of collections) + struct recElement * pSibling; // next sibling (for elements and collections) + + long depth; +}; +typedef struct recElement recElement; +typedef recElement* pRecElement; + +struct recDevice +{ + void * interface; // interface to device, NULL = no interface + void * queue; // device queue, NULL = no queue + void * queueRunLoopSource; // device queue run loop source, NULL == no source + void * transaction; // output transaction interface, NULL == no interface + void * notification; // notifications + char transport[256]; // device transport (c string) + long vendorID; // id for device vendor, unique across all devices + long productID; // id for particular product, unique across all of a vendors devices + long version; // version of product + char manufacturer[256]; // name of manufacturer + char product[256]; // name of product + char serial[256]; // serial number of specific product, can be assumed unique across specific product or specific vendor (not used often) + long locID; // long representing location in USB (or other I/O) chain which device is pluged into, can identify specific device on machine + long usage; // usage page from IOUSBHID Parser.h which defines general usage + long usagePage; // usage within above page from IOUSBHID Parser.h which defines specific usage + long totalElements; // number of total elements (should be total of all elements on device including collections) (calculated, not reported by device) + long features; // number of elements of type kIOHIDElementTypeFeature + long inputs; // number of elements of type kIOHIDElementTypeInput_Misc or kIOHIDElementTypeInput_Button or kIOHIDElementTypeInput_Axis or kIOHIDElementTypeInput_ScanCodes + long outputs; // number of elements of type kIOHIDElementTypeOutput + long collections; // number of elements of type kIOHIDElementTypeCollection + long axis; // number of axis (calculated, not reported by device) + long buttons; // number of buttons (calculated, not reported by device) + long hats; // number of hat switches (calculated, not reported by device) + long sliders; // number of sliders (calculated, not reported by device) + long dials; // number of dials (calculated, not reported by device) + long wheels; // number of wheels (calculated, not reported by device) + recElement* pListElements; // head of linked list of elements + struct recDevice* pNext; // next device +}; +typedef struct recDevice recDevice; +typedef recDevice* pRecDevice; + +// ================================== +// HID Utilities interface +// ================================== +// Create and open an interface to device, required prior to extracting values or building queues +// Note: appliction now owns the device and must close and release it prior to exiting +extern unsigned long HIDCreateOpenDeviceInterface (UInt32 hidDevice, pRecDevice pDevice); + +// builds list of device with elements (allocates memory and captures devices) +// list is allcoated internally within HID Utilites and can be accessed via accessor functions +// structures within list are considered flat and user accessable, butnot user modifiable +// can be called again to rebuild list to account for new devices (will do the right thing in case of disposing existing list) +extern Boolean HIDBuildDeviceList (UInt32 usagePage, UInt32 usage); + +// release list built by above function +// MUST be called prior to application exit to properly release devices +// if not called (or app crashes) devices can be recovered by pluging into different location in USB chain +extern void HIDReleaseDeviceList (void); + +// does a device list exist +extern Boolean HIDHaveDeviceList (void); + +// how many HID devices have been found +// returns 0 if no device list exist +extern UInt32 HIDCountDevices (void); + +// how many elements does a specific device have +// returns 0 if device is invalid or NULL +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get non-collection elements +extern UInt32 HIDCountDeviceElements (pRecDevice pDevice, HIDElementTypeMask typeMask); + +// get the first device in the device list +// returns NULL if no list exists +extern pRecDevice HIDGetFirstDevice (void); + +// get next device in list given current device as parameter +// returns NULL if end of list +extern pRecDevice HIDGetNextDevice (pRecDevice pDevice); + +// get the first element of device passed in as parameter +// returns NULL if no list exists or device does not exists or is NULL +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get previous HIDGetFirstDeviceElement functionality +extern pRecElement HIDGetFirstDeviceElement (pRecDevice pDevice, HIDElementTypeMask typeMask); + +// get next element of given device in list given current element as parameter +// will walk down each collection then to next element or collection (depthwise traverse) +// returns NULL if end of list +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get previous HIDGetNextDeviceElement functionality +extern pRecElement HIDGetNextDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask); + +// get previous element of given device in list given current element as parameter +// this wlaks directly up the tree to the top element and does not search at each level +// returns NULL if beginning of list +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get non-collection elements +extern pRecElement HIDGetPreviousDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask); + +// returns C string type name given a type enumeration passed in as parameter (see IOHIDKeys.h) +// returns empty string for invlid types +extern void HIDGetTypeName (IOHIDElementType theType, char * cstrName); + +// set name from vendor id/product id look up (using cookies) +extern Boolean HIDGetElementNameFromVendorProductCookie (const long vendorID, const long productID, const long cookie, char * pName); + +// set name from vendor id/product id look up (using usage page & usage) +extern Boolean HIDGetElementNameFromVendorProductUsage (const long vendorID, const long productID, const long pUsagePage, const long pUsage, char * pName); + +// returns C string usage given usage page and usage passed in as parameters (see IOUSBHIDParser.h) +// returns usage page and usage values in string form for unknown values +extern void HIDGetUsageName (long valueUsagePage, long valueUsage, char * cstrName); + +// returns calibrated value given raw value passed in +// calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values +extern SInt32 HIDCalibrateValue (SInt32 value, pRecElement pElement); + +// returns scaled value given raw value passed in +// scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values +extern SInt32 HIDScaleValue (SInt32 value, pRecElement pElement); + +// --------------------------------- +// convert an element type to a mask +extern HIDElementTypeMask HIDConvertElementTypeToMask (const long type); + +// find this device +extern Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice); + +// find the device and element for this action +// Device: serial, vendorID, productID, location, usagePage, usage +// Element: cookie, usagePage, usage, +extern Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement, + pRecDevice *ppFoundDevice, pRecElement *ppFoundElement); + +// find the device and element for this action +// Device: serial, vendorID, productID, location, usagePage, usage +// Element: cookie, usagePage, usage, + +extern Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement); + +// print out all of an elements information +extern int HIDPrintElement(const pRecElement pElement); + +// return true if this is a valid device pointer +extern Boolean HIDIsValidDevice(const pRecDevice pSearchDevice); + +// return true if this is a valid element pointer for this device +extern Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement); + +// ================================== +// Element Event Queue and Value Interfaces + +enum +{ + kDefaultUserMin = 0, // default user min and max used for scaling + kDefaultUserMax = 255 +}; + +enum +{ + kDeviceQueueSize = 50 // this is wired kernel memory so should be set to as small as possible + // but should account for the maximum possible events in the queue + // USB updates will likely occur at 100 Hz so one must account for this rate of + // if states change quickly (updates are only posted on state changes) +}; + +// ================================== +// queues specific element, performing any device queue set up required +extern unsigned long HIDQueueElement (pRecDevice pDevice, pRecElement pElement); + +// adds all elements to queue, performing any device queue set up required +extern unsigned long HIDQueueDevice (pRecDevice pDevice); + +// removes element for queue, if last element in queue will release queue and device +extern unsigned long HIDDequeueElement (pRecDevice pDevice, pRecElement pElement); + +// completely removes all elements from queue and releases queue and device +extern unsigned long HIDDequeueDevice (pRecDevice pDevice); + +// releases all device queues for quit or rebuild (must be called) +extern unsigned long HIDReleaseAllDeviceQueues (void); + +// releases interface to device, should be done prior to exiting application (called from HIDReleaseDeviceList) +extern unsigned long HIDCloseReleaseInterface (pRecDevice pDevice); + +// returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise +// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned char HIDGetEvent (pRecDevice pDevice, void * pHIDEvent); + +// returns current value for element, creating device interface as required, polling element +extern long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement); + +// Set an elements value +// NOTE: This should only be used when a single element report needs to be sent. +// If multiple elements reports are to be send then transactions should be used. +// pIOHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern long HIDSetElementValue (pRecDevice pDevice, pRecElement pElement,void* pIOHIDEvent); + +// Set a callback to be called when a queue goes from empty to non-empty +extern long HIDSetQueueCallback (pRecDevice pDevice, IOHIDCallbackFunction callback); + +#if 0 +// Get a report from a device +extern long HIDGetReport (pRecDevice pDevice,const IOHIDReportType reportType, const unsigned long reportID, void* reportBuffer, unsigned long* reportBufferSize); + +// Send a report to a device +extern long HIDSetReport (pRecDevice pDevice,const IOHIDReportType reportType, const unsigned long reportID, void* reportBuffer, const unsigned long reportBufferSize); +#endif + +// ================================== +// HUD utilities interfaces + +// returns calibrated value given raw value passed in +// calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values +extern long HIDCalibrateValue (long value, pRecElement pElement); + +// returns scaled value given raw value passed in +// scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values +extern long HIDScaleValue (long value, pRecElement pElement); + +// convert an element type to a mask +extern HIDElementTypeMask HIDConvertElementTypeToMask (const long type); + +// find this device +extern Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice); + +// find the device and element for this action +// Device: serial, vendorID, productID, location, usagePage, usage +// Element: cookie, usagePage, usage, +extern Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement, + pRecDevice *ppFoundDevice, pRecElement *ppFoundElement); +// find the device and element for this action +// Device: serial, vendorID, productID, location, usagePage, usage +// Element: cookie, usagePage, usage, + +extern Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement); + +// print out all of an elements information +extern int HIDPrintElement(const pRecElement pElement); + +// return true if this is a valid device pointer +extern Boolean HIDIsValidDevice(const pRecDevice pSearchDevice); + +// return true if this is a valid element pointer for this device +extern Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement); + +// ================================== +// Name Lookup Interfaces + +// set name from vendor id/product id look up (using cookies) +extern Boolean HIDGetElementNameFromVendorProductCookie (const long vendorID, const long productID, const long cookie, char * pName); + +// set name from vendor id/product id look up (using usage page & usage) +extern Boolean HIDGetElementNameFromVendorProductUsage (const long vendorID, const long productID, const long pUsagePage, const long pUsage, char * pName); + +// ================================== +// Conguration and Save Interfaces + +enum +{ + kPercentMove = 10 // precent of overall range a element must move to register +}; + +typedef struct recSaveHID +{ + long actionCookie; + // device + // need to add serial number when I have a test case + long vendorID; + long productID; + long locID; + long usage; + long usagePage; + // elements + long usagePageE; + long usageE; + void * cookie; +}recSaveHID,*pRecSaveHID; + +// polls all devices and elements for a change greater than kPercentMove. Times out after given time +// returns true and pointer to device and element if found +// returns false and NULL for both parameters if not found +extern unsigned char HIDConfigureAction (pRecDevice * ppDevice, pRecElement * ppElement, float timeout); + +// take input records, save required info +// assume file is open and at correct position. +extern void HIDSaveElementConfig (FILE * fileRef, pRecDevice pDevice, pRecElement pElement, long actionCookie); + +// take file, read one record (assume file position is correct and file is open) +// search for matching device +// return pDevice, pElement and cookie for action +extern long HIDRestoreElementConfig (FILE * fileRef, pRecDevice * ppDevice, pRecElement * ppElement); + +// Save the device & element values into the specified key in the specified applications preferences +extern Boolean HIDSaveElementPref (CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice pDevice, pRecElement pElement); + +// Find the specified preference in the specified application +// search for matching device and element +// return pDevice, pElement that matches + +extern Boolean HIDRestoreElementPref (CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice * ppDevice, pRecElement * ppElement); + +// ================================== +// Output Transaction interface + +// Create and open an transaction interface to device, required prior to extracting values or building Transactions +extern unsigned long HIDTransactionAddElement(pRecDevice pDevice, pRecElement pElement); + +// removes an element from a Transaction +extern unsigned long HIDTransactionRemoveElement(pRecDevice pDevice, pRecElement pElement); + +// return true if this transaction contains this element +extern Boolean HIDTransactionHasElement(pRecDevice pDevice, pRecElement pElement); + +/* This changes the default value of an element, when the values of the */ +/* elements are cleared, on clear or commit, they are reset to the */ +/* default value */ +/* This call can be made on elements that are not in the transaction, but */ +/* has undefined behavior if made on elements not in the transaction */ +/* which are later added to the transaction. */ +/* In other words, an element should be added before its default is */ +/* set, for well defined behavior. */ +// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned long HIDTransactionSetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); + +/* Get the current setting of an element's default value */ +// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned long HIDTransactionGetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); + +/* Add a change to the transaction, by setting an element value */ +/* The change is not actually made until it is commited */ +/* The element must be part of the transaction or this call will fail */ +// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned long HIDTransactionSetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); + +/* Get the current setting of an element value */ +// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned long HIDTransactionGetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); + +/* Commit the transaction, or clear all the changes and start over */ +/* timoutMS is the timeout in milliseconds, a zero timeout will cause */ +/* this call to be non-blocking (returning queue empty) if there */ +/* is a NULL callback, and blocking forever until the queue is */ +/* non-empty if their is a valid callback */ +/* callback, if non-NULL is a callback to be called when data is */ +/* inserted to the queue */ +/* callbackTarget and callbackRefcon are passed to the callback */ +extern unsigned long HIDTransactionCommit(pRecDevice pDevice); + +/* Clear all the changes and start over */ +extern unsigned long HIDTransactionClear(pRecDevice pDevice); + +// ================================== + +#ifdef __cplusplus +} +#endif + +#endif // _HID_Utilities_External_h_ diff --git a/HID_Config_Utilities.c b/HID_Config_Utilities.c new file mode 100755 index 0000000..a8e97b2 --- /dev/null +++ b/HID_Config_Utilities.c @@ -0,0 +1,425 @@ +/* + File: HID_Config_Utilities.c + + Contains: Implementation of the HID configuration utilities for the HID utilities. + + DRI: George Warner + + Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include // malloc +#include // clock + +#include + +#include "HID_Utilities_Internal.h" +#include "HID_Utilities_External.h" + +// --------------------------------- +// polls all devices and elements for a change greater than kPercentMove. Times out after given time +// returns 1 and pointer to device and element if found +// returns 0 and NULL for both parameters if not found + +unsigned char HIDConfigureAction (pRecDevice * ppDevice, pRecElement * ppElement, float timeout) +{ + long numDevices, maxElements = 0; + long * saveValueArray; + pRecDevice pDevice = NULL; + pRecElement pElement = NULL; + short deviceNum = 0; + unsigned char found = 0, done = 0; + clock_t start = clock (), end; + + if (!HIDHaveDeviceList ()) // if we do not have a device list + if (0 == HIDBuildDeviceList (kHIDPage_GenericDesktop, 0)) // if we could not build another list (use generic page) + return 0; // return 0 + + // build list of device and elements to save current values + numDevices = HIDCountDevices (); + pDevice = HIDGetFirstDevice (); + while (pDevice) + { + long numElements = HIDCountDeviceElements (pDevice, kHIDElementTypeInput); + if (numElements > maxElements) + maxElements = numElements; + pDevice = HIDGetNextDevice (pDevice); + } + saveValueArray = (long *) malloc (sizeof (long) * numDevices * maxElements); // 2D array to save values + bzero(saveValueArray,sizeof (long) * numDevices * maxElements); // clear array + + // store current values + deviceNum = 0; + pDevice = HIDGetFirstDevice (); + while (pDevice) + { + short elementNum = 0; + pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeInput); + while (pElement) + { + *(saveValueArray + (deviceNum * maxElements) + elementNum) = HIDGetElementValue (pDevice, pElement); + pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeInput); + elementNum++; + } + pDevice = HIDGetNextDevice (pDevice); + deviceNum++; + } + + // poll all devices and elements, compare current value to save +/- kPercentMove + while ((!found) && (!done)) + { + double secs; + // are we done? + end = clock(); + secs = (double)(end - start) / CLOCKS_PER_SEC; + if (secs > timeout) + done = 1; + deviceNum = 0; + pDevice = HIDGetFirstDevice (); + while (pDevice) + { + short elementNum = 0; + pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeInput); + while (pElement) + { + // ignore force feedback devices AND arrays + if ((kHIDPage_PID != pElement->usagePage) && (-1 != pElement->usage)) + { + long initialValue = *(saveValueArray + (deviceNum * maxElements) + elementNum); + long value = HIDGetElementValue (pDevice, pElement); + long delta = (float)(pElement->max - pElement->min) * kPercentMove * 0.01; + + if (((initialValue + delta) < value) || ((initialValue - delta) > value)) + { + found = 1; + break; + } + } + pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeInput); + elementNum++; + } + if (found) + break; + pDevice = HIDGetNextDevice (pDevice); + deviceNum++; + } + } + + // return device and element moved + if (found) + { + *ppDevice = pDevice; + *ppElement = pElement; + return 1; + } + else + { + *ppDevice = NULL; + *ppElement = NULL; + return 0; + } +} + +// --------------------------------- +// takes input records, save required info +// assume file is open and at correct position. +// will always write to file (if file exists) size of recSaveHID, even if device and or element is bad + +void HIDSaveElementConfig (FILE * fileRef, pRecDevice pDevice, pRecElement pElement, long actionCookie) +{ + recSaveHID saveRec; + + if (HIDIsValidElement(pDevice,pElement)) + { + // clear rec + bzero(&saveRec,sizeof(recSaveHID)); + + saveRec.actionCookie = actionCookie; + + // must save + // actionCookie + // Device: serial,vendorID, productID, location, usagePage, usage + // Element: cookie, usagePage, usage, + // need to add serial number when I have a test case + + saveRec.vendorID = pDevice->vendorID; + saveRec.productID = pDevice->productID; + saveRec.locID = pDevice->locID; + saveRec.usage = pDevice->usage; + saveRec.usagePage = pDevice->usagePage; + + saveRec.usagePageE = pElement->usagePage; + saveRec.usageE = pElement->usage; + saveRec.cookie = pElement->cookie; + + // write to file + if (fileRef) + fwrite ((void *)&saveRec, sizeof (recSaveHID), 1, fileRef); + } +} + +// --------------------------------- +// take file, read one record (assume file position is correct and file is open) +// search for matching device +// return pDevice, pElement and cookie for action + +long HIDRestoreElementConfig (FILE * fileRef, pRecDevice * ppDevice, pRecElement * ppElement) +{ + // Device: serial,vendorID, productID, location, usagePage, usage + // Element: cookie, usagePage, usage, + + pRecDevice pDevice, pFoundDevice = NULL; + pRecElement pElement, pFoundElement = NULL; + + recSaveHID restoreRec; + + fread ((void *) &restoreRec, 1, sizeof (recSaveHID), fileRef); + + // compare to current device list for matches + // look for device + if (restoreRec.locID && restoreRec.vendorID && restoreRec.productID) + { // look for specific device type plug in to same port + pDevice = HIDGetFirstDevice (); + while (pDevice) + { + if ((restoreRec.locID == pDevice->locID) && + (restoreRec.vendorID == pDevice->vendorID) && + (restoreRec.productID == pDevice->productID)) + pFoundDevice = pDevice; + if (pFoundDevice) + break; + pDevice = HIDGetNextDevice (pDevice); + } + if (pFoundDevice) + { + pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); + while (pElement) + { + if (restoreRec.cookie == pElement->cookie) + pFoundElement = pElement; + if (pFoundElement) + break; + pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); + } + // if no cookie match (should NOT occur) match on usage + pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); + while (pElement) + { + if ((restoreRec.usageE == pElement->usage) && + (restoreRec.usagePageE == pElement->usagePage)) + pFoundElement = pElement; + if (pFoundElement) + break; + pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); + } + } + } + // if we have not found a match, look at just vendor and product + if ((NULL == pFoundDevice) && + (restoreRec.vendorID && restoreRec.productID)) + { + pDevice = HIDGetFirstDevice (); + while (pDevice) + { + if ((restoreRec.vendorID == pDevice->vendorID) && + (restoreRec.productID == pDevice->productID)) + pFoundDevice = pDevice; + if (pFoundDevice) + break; + pDevice = HIDGetNextDevice (pDevice); + } + // match elements by cookie since same device type + if (pFoundDevice) + { + pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); + while (pElement) + { + if (restoreRec.cookie == pElement->cookie) + pFoundElement = pElement; + if (pFoundElement) + break; + pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); + } + // if no cookie match (should NOT occur) match on usage + pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); + while (pElement) + { + if ((restoreRec.usageE == pElement->usage) && + (restoreRec.usagePageE == pElement->usagePage)) + pFoundElement = pElement; + if (pFoundElement) + break; + pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); + } + } + } + // if we have not found a match look for just same type of device + if ((NULL == pFoundDevice) && (restoreRec.usage && restoreRec.usagePage)) + { + pDevice = HIDGetFirstDevice (); + while (pDevice) + { + if ((restoreRec.usage == pDevice->usage) && (restoreRec.usagePage == pDevice->usagePage)) + pFoundDevice = pDevice; + if (pFoundDevice) + break; + pDevice = HIDGetNextDevice (pDevice); + } + // match elements by type + if (pFoundDevice) + { + pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); + while (pElement) + { + if ((restoreRec.usageE == pElement->usage) && + (restoreRec.usagePageE == pElement->usagePage)) + pFoundElement = pElement; + if (pFoundElement) + break; + pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); + } + } + } + // if still not found just get first device + if (NULL == pFoundDevice) + { + pFoundDevice = HIDGetFirstDevice (); + // match elements by type + if (pFoundDevice) + { + pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); + while (pElement) + { + if ((restoreRec.usageE == pElement->usage) && + (restoreRec.usagePageE == pElement->usagePage)) + pFoundElement = pElement; + if (pFoundElement) + break; + pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); + } + } + } + if ((NULL == pFoundDevice) || (NULL == pFoundElement)) + { + // no HID device + *ppDevice = NULL; + *ppElement = NULL; + return restoreRec.actionCookie; + } + else + { + // no HID device + *ppDevice = pFoundDevice; + *ppElement = pFoundElement; + return restoreRec.actionCookie; + } + +} + +// --------------------------------- +// Find the specified preference in the specified application +// search for matching device and element +// return pDevice, pElement that matches + +Boolean HIDRestoreElementPref (CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice * ppDevice, pRecElement * ppElement) +{ + Boolean found = false; + + if ((NULL != keyCFStringRef) && (NULL != appCFStringRef) && (NULL != ppDevice) && (NULL != ppElement)) + { + CFPropertyListRef prefCFPropertyListRef = CFPreferencesCopyAppValue(keyCFStringRef, appCFStringRef); + + if (NULL != prefCFPropertyListRef) + { + if (CFStringGetTypeID() == CFGetTypeID(prefCFPropertyListRef)) + { + char buffer[256]; + + if (CFStringGetCString((CFStringRef) prefCFPropertyListRef, buffer, sizeof(buffer), kCFStringEncodingASCII)) + { + recDevice searchDevice; + recElement searchElement; + int count = sscanf(buffer, "d:{v:%ld, p:%ld, l:%ld, p:%ld, u:%ld}, e:{t:%ld, p:%ld, u:%ld, c:%ld}", + &searchDevice.vendorID, &searchDevice.productID, &searchDevice.locID, &searchDevice.usagePage, &searchDevice.usage, + &searchElement.type, &searchElement.usagePage, &searchElement.usage, (long*) &searchElement.cookie); + + if (9 == count) // if we found all nine parametersÉ + { // and can find a device & element that matches theseÉ + if (HIDFindActionDeviceAndElement(&searchDevice, &searchElement,ppDevice, ppElement)) + { + found = true; + } + } + } + } + else + { + // We found the entry with this key but it's the wrong type; delete it. + CFPreferencesSetAppValue(keyCFStringRef, NULL, appCFStringRef); + (void) CFPreferencesAppSynchronize(appCFStringRef); + } + CFRelease(prefCFPropertyListRef); + } + } + return found; +} + +// --------------------------------- +// Save the device & element values into the specified key in the specified applications preferences + +Boolean HIDSaveElementPref (const CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice pDevice, pRecElement pElement) +{ + Boolean success = false; + + if ((NULL != keyCFStringRef) && (NULL != appCFStringRef) && HIDIsValidElement(pDevice,pElement)) + { + CFStringRef prefCFStringRef = + CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("d:{v:%ld, p:%ld, l:%ld, p:%ld, u:%ld}, e:{t:%ld, p:%ld, u:%ld, c:%ld}"), + pDevice->vendorID, pDevice->productID, pDevice->locID, pDevice->usagePage, pDevice->usage, + pElement->type, pElement->usagePage, pElement->usage, pElement->cookie); + + if (NULL != prefCFStringRef) + { + CFPreferencesSetAppValue(keyCFStringRef, prefCFStringRef, kCFPreferencesCurrentApplication); + CFRelease(prefCFStringRef); + success = true; + } + } + return success; +} diff --git a/HID_Error_Handler.c b/HID_Error_Handler.c new file mode 100755 index 0000000..2985fce --- /dev/null +++ b/HID_Error_Handler.c @@ -0,0 +1,104 @@ +/* + File: Error Handler.c + + Contains: Implementation of the HID utility error handlers for the HID Utilities + + DRI: George Warner + + Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#if !defined (kBuildingLibrary) + #define kVerboseErrors + +// system includes ---------------------------------------------------------- + + #ifdef kVerboseErrors + #include + #endif +#endif // not kBuildingLibrary + +#include + +// project includes --------------------------------------------------------- + +#include "HID_Utilities_Internal.h" + +// globals (internal/private) ----------------------------------------------- + +// prototypes (internal/private) -------------------------------------------- + +// functions (internal/private) --------------------------------------------- + +#pragma mark - +// ------------------------------------- + +// central error reporting + +void HIDReportErrorNum (char * strError, long numError) +{ + char errMsgCStr [256]; + + sprintf (errMsgCStr, "%s #%ld (0x%lx)", strError, numError, numError); + + // out as debug string +#ifdef kVerboseErrors + { + Str255 strErr = "\p"; + CopyCStringToPascal (errMsgCStr, strErr); + DebugStr (strErr); + } +#endif // kVerboseErrors +} + +// ------------------------------------- + +void HIDReportError (char * strError) +{ + char errMsgCStr [256]; + + sprintf (errMsgCStr, "%s", strError); + + // out as debug string +#ifdef kVerboseErrors + { + Str255 strErr = "\p"; + CopyCStringToPascal (errMsgCStr, strErr); + DebugStr (strErr); + } +#endif // kVerboseErrors +} diff --git a/HID_Error_Handler.h b/HID_Error_Handler.h new file mode 100755 index 0000000..a672182 --- /dev/null +++ b/HID_Error_Handler.h @@ -0,0 +1,74 @@ +/* + File: HID_Error_Handler.h + + Contains: Definition of the interfaces to + + DRI: George Warner + + Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +// Usage notes: + +// include control -------------------------------------------------- + +#ifndef Error_Handler_h +#define Error_Handler_h + +// includes --------------------------------------------------------- + +#ifdef __cplusplus +extern "C" { +#endif + +// structures (public) ----------------------------------------------- + +// public function declarations ------------------------------------- + +// Error reporter, can be set to report however the application desires +extern void HIDReportError (char * strError); + +// Error with numeric code reporter, can be set to report however the application desires +extern void HIDReportErrorNum (char * strError, long numError); + +#ifdef __cplusplus +} +#endif + +#endif // Error_Handler_h \ No newline at end of file diff --git a/HID_Name_Lookup.c b/HID_Name_Lookup.c new file mode 100755 index 0000000..7b2fe6f --- /dev/null +++ b/HID_Name_Lookup.c @@ -0,0 +1,347 @@ +/* + File: HID_Name_Lookup.c + + Contains: Implementation of the HID device name lookup functions for the HID utilites. + + DRI: George Warner + + Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "HID_Utilities_Internal.h" +#include "HID_Name_Lookup.h" + +#define FAKE_IT 0 // set true for debugging; returns the vendor, product & cookie (or usage info) as numbers. + +// --------------------------------- +// Load the element strings from the given resource (XML) file into a CFPropertyListRef +static CFPropertyListRef xml_load(const CFStringRef pResourceName,const CFStringRef pResourceExtension) +{ + CFPropertyListRef tCFPropertyListRef = NULL; + CFURLRef resFileCFURLRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), pResourceName, pResourceExtension, NULL); + + if (NULL != resFileCFURLRef) + { + CFDataRef resCFDataRef; + + if (CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, resFileCFURLRef, &resCFDataRef, nil, nil, nil)) + { + if (NULL != resCFDataRef) + { + CFStringRef errorString; + + tCFPropertyListRef = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resCFDataRef, kCFPropertyListImmutable, &errorString); + if (NULL == tCFPropertyListRef) + CFShow(errorString); + CFRelease(resCFDataRef); + } + } + CFRelease(resFileCFURLRef); + } + return tCFPropertyListRef; +} + +// --------------------------------- +// Find an element string in the resource (XML) file +static Boolean xml_search_cookie(const long pVendorID, const long pProductID, const long pCookie, char* pCstr) +{ + static CFPropertyListRef tCFPropertyListRef = NULL; + Boolean results = false; + + if (NULL == tCFPropertyListRef) + tCFPropertyListRef = xml_load(CFSTR("HID_cookie_strings"), CFSTR("plist")); + if (NULL != tCFPropertyListRef) + { + if (CFDictionaryGetTypeID() == CFGetTypeID(tCFPropertyListRef)) + { + CFDictionaryRef vendorCFDictionaryRef; + CFStringRef vendorKeyCFStringRef; + vendorKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pVendorID); + + if (CFDictionaryGetValueIfPresent(tCFPropertyListRef, vendorKeyCFStringRef, (const void**) &vendorCFDictionaryRef)) + { + CFDictionaryRef productCFDictionaryRef; + CFStringRef productKeyCFStringRef; + CFStringRef vendorCFStringRef; + + if (CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, CFSTR("Name"), (const void**) &vendorCFStringRef)) + { + //CFShow(vendorCFStringRef); + } + productKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pProductID); + + if (CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, productKeyCFStringRef, (const void**) &productCFDictionaryRef)) + { + CFStringRef fullCFStringRef = NULL; + CFStringRef cookieKeyCFStringRef; + CFStringRef productCFStringRef; + CFStringRef cookieCFStringRef; + + if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, CFSTR("Name"), (const void**) &productCFStringRef)) + { + //CFShow(productCFStringRef); + } + cookieKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pCookie); + + if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, cookieKeyCFStringRef, (const void**) &cookieCFStringRef)) + { + fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ %@"), + vendorCFStringRef, productCFStringRef, cookieCFStringRef); + // CFShow(cookieCFStringRef); + } +#if FAKE_IT + else + { + fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ #%@"), + vendorCFStringRef, productCFStringRef, cookieKeyCFStringRef); + } +#endif + if (fullCFStringRef) + { + // CFShow(fullCFStringRef); + results = CFStringGetCString( + fullCFStringRef, pCstr, CFStringGetLength(fullCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingMacRoman); + CFRelease(fullCFStringRef); + } + CFRelease(cookieKeyCFStringRef); + } + CFRelease(productKeyCFStringRef); + } + CFRelease(vendorKeyCFStringRef); + } + //++CFRelease(tCFPropertyListRef); // Leak this! + } + return results; +} + +// --------------------------------- +// Find an element string in the resource (XML) file +static Boolean xml_search_usage(const long pVendorID, const long pProductID, const long pUsagePage, const long pUsage, char* pCstr) +{ + static CFPropertyListRef tCFPropertyListRef = NULL; + Boolean results = false; + + if (NULL == tCFPropertyListRef) + tCFPropertyListRef = xml_load(CFSTR("HID_device_usage_strings"), CFSTR("plist")); + if (NULL != tCFPropertyListRef) + { + if (CFDictionaryGetTypeID() == CFGetTypeID(tCFPropertyListRef)) + { + CFDictionaryRef vendorCFDictionaryRef; + CFStringRef vendorKeyCFStringRef; + vendorKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pVendorID); + + if (CFDictionaryGetValueIfPresent(tCFPropertyListRef, vendorKeyCFStringRef, (const void**) &vendorCFDictionaryRef)) + { + CFDictionaryRef productCFDictionaryRef; + CFStringRef productKeyCFStringRef; + CFStringRef vendorCFStringRef; + + if (!CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, CFSTR("Name"), (const void**) &vendorCFStringRef)) + { + vendorCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("v: %ld"), pVendorID); + //CFShow(vendorCFStringRef); + } + productKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pProductID); + + if (CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, productKeyCFStringRef, (const void**) &productCFDictionaryRef)) + { + CFStringRef fullCFStringRef = NULL; + CFStringRef usageKeyCFStringRef; + CFStringRef productCFStringRef; + CFStringRef usageCFStringRef; + + if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, CFSTR("Name"), (const void**) &productCFStringRef)) + { + //CFShow(productCFStringRef); + } + usageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld:%ld"), pUsagePage, pUsage); + + if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, usageKeyCFStringRef, (const void**) &usageCFStringRef)) + { + fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ %@"), + vendorCFStringRef, productCFStringRef, usageCFStringRef); + // CFShow(usageCFStringRef); + } +#if FAKE_IT + else + { + fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ #%@"), + vendorCFStringRef, productCFStringRef, usageKeyCFStringRef); + } +#endif + if (fullCFStringRef) + { + // CFShow(fullCFStringRef); + results = CFStringGetCString( + fullCFStringRef, pCstr, CFStringGetLength(fullCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingMacRoman); + CFRelease(fullCFStringRef); + } + CFRelease(usageKeyCFStringRef); + } + CFRelease(productKeyCFStringRef); + } + CFRelease(vendorKeyCFStringRef); + } + //++CFRelease(tCFPropertyListRef); // Leak this! + } + return results; +} + +// --------------------------------- +// set name from vendor id/product id look up +Boolean HIDGetElementNameFromVendorProductCookie (const long pVendorID, const long pProductID, const long pCookie, char * pName) +{ + Boolean result = false; + *pName = 0; // clear name + + if (xml_search_cookie(pVendorID, pProductID, pCookie, pName)) + return true; + + switch (pVendorID) { + case kMacally: + switch (pProductID) { + case kiShock: + result = true; + switch (pCookie) { + case 3: sprintf(pName, "D-Pad Up"); break; + case 4: sprintf(pName, "D-Pad Down"); break; + case 5: sprintf(pName, "D-Pad Left"); break; + case 6: sprintf(pName, "D-Pad Right"); break; + case 7: sprintf(pName, "Up Button"); break; + case 8: sprintf(pName, "Right Button"); break; + case 9: sprintf(pName, "Down Button"); break; + case 10: sprintf(pName, "Left Button"); break; + case 11: sprintf(pName, "C Button"); break; + case 12: sprintf(pName, "B Button [Select]"); break; + case 13: sprintf(pName, "A Button [Start]"); break; + case 14: sprintf(pName, "F Button"); break; + case 15: sprintf(pName, "R1 Trigger"); break; + case 16: sprintf(pName, "R2 Trigger"); break; + case 17: sprintf(pName, "L1 Trigger"); break; + case 18: sprintf(pName, "L2 Trigger"); break; + case 19: sprintf(pName, "Left Stick Button"); break; + case 20: sprintf(pName, "Right Stick Button"); break; + case 21: sprintf(pName, "D Button"); break; + case 22: sprintf(pName, "E Button"); break; + case 23: sprintf(pName, "Left Stick X-Axis"); break; + case 24: sprintf(pName, "Left Stick Y-Axis"); break; + case 25: sprintf(pName, "Right Stick X-Axis"); break; + case 26: sprintf(pName, "Right Stick Y-Axis"); break; + default: +#if FAKE_IT + sprintf(pName, "#{V:Macally, P:iShock, C:%ld}#", pCookie); +#else + result = false; +#endif FAKE_IT + break; + } + break; + default: +#if FAKE_IT + sprintf(pName, "#{V:Macally, P:%ld, C:%ld}#", pProductID, pCookie); break; +#else + result = false; +#endif FAKE_IT + break; + } + break; + case kMacsense: + switch (pProductID) { + case kFunPadF107: + result = true; + switch (pCookie) { + case 3: sprintf(pName, "Button 1"); break; + case 4: sprintf(pName, "Button 2"); break; + case 5: sprintf(pName, "Button 3"); break; + case 6: sprintf(pName, "Button 4"); break; + case 7: sprintf(pName, "L1 Trigger"); break; + case 8: sprintf(pName, "R1 Trigger"); break; + case 9: sprintf(pName, "L2 Trigger"); break; + case 10: sprintf(pName, "R2 Trigger"); break; + case 11: sprintf(pName, "Right Stick X-Axis"); break; + case 12: sprintf(pName, "Right Stick Y-Axis"); break; + case 13: sprintf(pName, "Left Stick X-Axis"); break; + case 14: sprintf(pName, "Left Stick Y-Axis"); break; + case 15: sprintf(pName, "Hat Switch"); break; + default: +#if FAKE_IT + sprintf(pName, "#{V:Macsense, P:FunPad F-107, C:%ld}#", pCookie); +#else + result = false; +#endif FAKE_IT + break; + } + default: +#if FAKE_IT + sprintf(pName, "#{V:Macsense, P:%ld, C:%ld}#", pProductID, pCookie); +#else + result = false; +#endif FAKE_IT + break; + } + break; + default: +#if FAKE_IT + sprintf(pName, "#{V:%ld, P:%ld, C:%ld}#", pVendorID, pProductID, pCookie); +#else + result = false; +#endif FAKE_IT + break; + } + return result; +} + + +// --------------------------------- +// set name from vendor id/product id & usage look up +Boolean HIDGetElementNameFromVendorProductUsage (const long pVendorID, const long pProductID, const long pUsagePage, const long pUsage, char * pName) +{ + Boolean result = false; + *pName = 0; // clear name + + if (xml_search_usage(pVendorID, pProductID, pUsagePage, pUsage, pName)) + return true; + +#if FAKE_IT + sprintf(pName, "#{V:%ld, P:%ld, U:%ld:%ld}#", pVendorID, pProductID, pUsagePage, pUsage); + result = true; +#endif + + return result; +} diff --git a/HID_Name_Lookup.h b/HID_Name_Lookup.h new file mode 100755 index 0000000..5615172 --- /dev/null +++ b/HID_Name_Lookup.h @@ -0,0 +1,87 @@ +/* + File: HID_Name_Lookup.h + + Contains: Definition of the HID device name lookup functions for the HID utilites. + + DRI: George Warner + + Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _HID_Name_Lookup_h_ +#define _HID_Name_Lookup_h_ + +#include "HID_Utilities.h" + +// ================================== + +#ifdef __cplusplus +extern "C" { +#endif + +// ================================== +// Note: Now that as the device data has now been moved into external .XML files these +// constansts should no longer be used. They will eventually be eliminated from this header. + +#define kMicrosoft 1118 +#define kSideWinderFFB2 27 + +#define kLogitech 1133 +#define kWingManStrikeForce3D 49797 + +#define kMacally 8738 +#define kiShock 16400 +#define kiShockIIFFB 16416 + +#define kMacsense 1635 +#define kFunPadF107 38916 +// ================================== + +// set name from vendor id/product id look up (using cookies) +extern Boolean HIDGetElementNameFromVendorProductCookie (const long vendorID, const long productID, const long cookie, char * pName); + +// set name from vendor id/product id look up (using usage page & usage) +extern Boolean HIDGetElementNameFromVendorProductUsage (const long vendorID, const long productID, const long pUsagePage, const long pUsage, char * pName); +// ================================== + +#ifdef __cplusplus +} +#endif + +#endif // _HID_Name_Lookup_h_ + diff --git a/HID_Queue_Utilities.c b/HID_Queue_Utilities.c new file mode 100755 index 0000000..c4e37a3 --- /dev/null +++ b/HID_Queue_Utilities.c @@ -0,0 +1,632 @@ +/* + File: HID_Queue_Utilities.c + + Contains: Implementation of the HID queue functions for the HID utilites. + + DRI: George Warner + + Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +//#include + +#include "HID_Utilities_Internal.h" +#include "HID_Utilities_External.h" + +// ================================== +// compiler directives +// ================================== +#define USE_ASYNC_EVENTS TRUE +#define REPORT_ERRORS FALSE +// ================================== +#if REPORT_ERRORS +#define HIDREPORTERRORNUM(s,n) HIDReportErrorNum(s,n) +#define HIDREPORTERROR(s) HIDReportError(s) +#else +#define HIDREPORTERRORNUM(s,n) do {} while (false) +#define HIDREPORTERROR(s) do {} while (false) +#endif +// ================================== +// private functions +// ================================== + +// creates a queue for a device + +static IOReturn hid_CreateQueue (pRecDevice pDevice) +{ + IOReturn result = kIOReturnError; // assume failure (pessimist!) + + if (HIDIsValidDevice(pDevice)) + { + if (NULL == pDevice->queue) // do we already have a queue + { + if (NULL != pDevice->interface) + { + pDevice->queue = (void *) (*(IOHIDDeviceInterface**) pDevice->interface)->allocQueue (pDevice->interface); // alloc queue + if (pDevice->queue) + { + result = (*(IOHIDQueueInterface**) pDevice->queue)->create (pDevice->queue, 0, kDeviceQueueSize); // create actual queue + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("hid_CreateQueue - Failed to create queue via create", result); + } + else + { + HIDREPORTERROR ("hid_CreateQueue - Failed to alloc IOHIDQueueInterface ** via allocQueue"); + result = kIOReturnError; // synthesis error + } + } + else + HIDREPORTERRORNUM ("hid_CreateQueue - Device inteface does not exist for queue creation", result); + } + } + else + HIDREPORTERRORNUM ("hid_CreateQueue - Invalid Device", result); + return result; +} + +// --------------------------------- +// returns true if queue is empty false otherwise +// error if no device, empty if no queue + +static unsigned char hid_IsDeviceQueueEmpty (pRecDevice pDevice) +{ + if (HIDIsValidDevice(pDevice)) // need valid device + { + if (pDevice->queue) // and queue + { + pRecElement pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO); + while (pElement) + { + if ((*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) + return false; + pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); + } + } + else + HIDREPORTERROR ("hid_IsDeviceQueueEmpty - no queue."); + } + else + HIDREPORTERROR ("hid_IsDeviceQueueEmpty - Invalid device."); + return true; +} + +// --------------------------------- +// disposes and releases queue, sets queue to NULL,. +// Note: will have no effect if device or queue do not exist + +static IOReturn hid_DisposeReleaseQueue (pRecDevice pDevice) +{ + IOReturn result = kIOReturnError; // assume failure (pessimist!) + + if (HIDIsValidDevice(pDevice)) // need valid device + { + if (pDevice->queue) // and queue + { + // stop queue + result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("hid_DisposeReleaseQueue - Failed to stop queue.", result); + // dispose of queue + result = (*(IOHIDQueueInterface**) pDevice->queue)->dispose (pDevice->queue); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("hid_DisposeReleaseQueue - Failed to dipose queue.", result); + // release the queue + result = (*(IOHIDQueueInterface**) pDevice->queue)->Release (pDevice->queue); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("hid_DisposeReleaseQueue - Failed to release queue.", result); + + pDevice->queue = NULL; + } + else + HIDREPORTERROR ("hid_DisposeReleaseQueue - no queue."); + } + else + HIDREPORTERROR ("hid_DisposeReleaseQueue - Invalid device."); + return result; +} + +// ================================== +// public functions + +// --------------------------------- +// queues specific element, performing any device queue set up required +// queue is started and ready to return events on exit from this function + +unsigned long HIDQueueElement (pRecDevice pDevice, pRecElement pElement) +{ + IOReturn result = kIOReturnError; // assume failure (pessimist!) + + if (HIDIsValidElement(pDevice,pElement)) + { + if (NULL == pDevice->interface) // must have interface + { + HIDREPORTERROR ("HIDQueueElement - Device does not have interface."); + return kIOReturnError; + } + if (NULL == pDevice->queue) // if no queue create queue + result = hid_CreateQueue (pDevice); + if ((kIOReturnSuccess != result) || (NULL == pDevice->queue)) + { + HIDREPORTERRORNUM ("HIDQueueElement - problem creating queue.", result); + if (kIOReturnSuccess != result) + return result; + else + return kIOReturnError; + } + + // stop queue + result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue); + if (kIOReturnSuccess != result) + HIDREPORTERROR ("HIDQueueElement - Failed to stop queue."); + + // queue element + if (!(*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) + { + result = (*(IOHIDQueueInterface**) pDevice->queue)->addElement (pDevice->queue, pElement->cookie, 0); + if (kIOReturnSuccess != result) + HIDREPORTERROR ("HIDQueueElement - Failed to add Element to queue."); + } + + // restart queue + result = (*(IOHIDQueueInterface**) pDevice->queue)->start (pDevice->queue); + if (kIOReturnSuccess != result) + HIDREPORTERROR ("HIDQueueElement - Failed to start queue."); + } + else + { + HIDREPORTERROR ("HIDQueueElement - Invalid Device and/or element."); + return kIOReturnBadArgument; + } + + return result; +} + +// --------------------------------- +// adds all elements to queue, performing any device queue set up required +// queue is started and ready to return events on exit from this function + +unsigned long HIDQueueDevice (pRecDevice pDevice) +{ + IOReturn result = kIOReturnError; // assume failure (pessimist!) + pRecElement pElement; + + if (HIDIsValidDevice(pDevice)) + { + // error checking + if (NULL == pDevice) + { + HIDREPORTERROR ("HIDQueueDevice - Device does not exist."); + return kIOReturnBadArgument; + } + if (NULL == pDevice->interface) // must have interface + { + HIDREPORTERROR ("HIDQueueDevice - Device does not have interface."); + return kIOReturnError; + } + if (NULL == pDevice->queue) // if no queue create queue + result = hid_CreateQueue (pDevice); + if ((kIOReturnSuccess != result) || (NULL == pDevice->queue)) + { + HIDREPORTERRORNUM ("HIDQueueDevice - problem creating queue.", result); + if (kIOReturnSuccess != result) + return result; + else + return kIOReturnError; + } + + // stop queue + result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDQueueDevice - Failed to stop queue.", result); + + // queue element + //¥ pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO); + pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeInput | kHIDElementTypeFeature); + + while (pElement) + { + if (!(*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) + { + result = (*(IOHIDQueueInterface**) pDevice->queue)->addElement (pDevice->queue, pElement->cookie, 0); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDQueueDevice - Failed to add element to queue.", result); + } + //¥ pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); + pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeInput | kHIDElementTypeFeature); + } + + // start queue + result = (*(IOHIDQueueInterface**) pDevice->queue)->start (pDevice->queue); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDQueueDevice - Failed to start queue.", result); + + } + else + HIDREPORTERROR ("HIDQueueDevice - Invalid device."); + + return result; +} + +// --------------------------------- +// removes element for queue, if last element in queue will release queue and closes device interface + +unsigned long HIDDequeueElement (pRecDevice pDevice, pRecElement pElement) +{ + IOReturn result = kIOReturnError; // assume failure (pessimist!) + + if (HIDIsValidElement(pDevice,pElement)) + { + if (!pDevice || !pElement) + result = kIOReturnBadArgument; + else + { + if ((pDevice->interface) && (pDevice->queue)) + { + // stop queue + result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDDequeueElement - Failed to stop queue.", result); + + if ((*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) // if has element then remove + { + result = (*(IOHIDQueueInterface**) pDevice->queue)->removeElement (pDevice->queue, pElement->cookie); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDDequeueElement - Failed to add element to queue", result); + } + + if (hid_IsDeviceQueueEmpty (pDevice)) // release device queue and close interface if queue empty + { + result = hid_DisposeReleaseQueue (pDevice); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDDequeueElement - Failed to dispose and release queue.", result); + } + else // not empty so restart queue + { + result = (*(IOHIDQueueInterface**) pDevice->queue)->start (pDevice->queue); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDDequeueElement - Failed to start queue.", result); + } + } + else + { + HIDREPORTERROR ("HIDDequeueElement - No device inteface or queue."); + return kIOReturnError; + } + } + } + else + HIDREPORTERROR ("HIDDequeueElement - Invalid device."); + + return result; +} + +// --------------------------------- +// completely removes all elements from queue and releases queue and closes device interface +// does not release device interfaces, application must call HIDReleaseDeviceList on exit + +unsigned long HIDDequeueDevice (pRecDevice pDevice) +{ + IOReturn result = kIOReturnSuccess; + + if (HIDIsValidDevice(pDevice)) + { + if ((pDevice->interface) && (pDevice->queue)) + { + // iterate through elements and if queued, remove + pRecElement pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO); + while (pElement) + { + if ((*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) + { + result = (*(IOHIDQueueInterface**) pDevice->queue)->removeElement (pDevice->queue, pElement->cookie); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDDequeueDevice - Failed to remove element from queue.", result); + } + pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); + } + } + // ensure queue is disposed and released + // interface will be closed and released on call to HIDReleaseDeviceList + result = hid_DisposeReleaseQueue (pDevice); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("removeElement - Failed to dispose and release queue.", result); +#if USE_ASYNC_EVENTS + else if (NULL != pDevice->queueRunLoopSource) + { + if (CFRunLoopContainsSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode)) + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode); + CFRelease(pDevice->queueRunLoopSource); + pDevice->queueRunLoopSource = NULL; + } +#endif USE_ASYNC_EVENTS + } + else + { + HIDREPORTERROR ("HIDDequeueDevice - Invalid device."); + result = kIOReturnBadArgument; + } + return result; +} + +// --------------------------------- +// releases all device queues for quit or rebuild (must be called) +// does not release device interfaces, application must call HIDReleaseDeviceList on exit + +unsigned long HIDReleaseAllDeviceQueues (void) +{ + IOReturn result = kIOReturnBadArgument; + pRecDevice pDevice = HIDGetFirstDevice (); + + while (pDevice) + { + result = HIDDequeueDevice (pDevice); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDReleaseAllDeviceQueues - Could not dequeue device.", result); + pDevice = HIDGetNextDevice (pDevice); + } + return result; +} + +// --------------------------------- +// Closes and releases interface to device, should be done prior to exting application +// Note: will have no affect if device or interface do not exist +// application will "own" the device if interface is not closed +// (device may have to be plug and re-plugged in different location to get it working again without a restart) + +unsigned long HIDCloseReleaseInterface (pRecDevice pDevice) +{ + IOReturn result = kIOReturnSuccess; + + if (HIDIsValidDevice(pDevice) && (NULL != pDevice->interface)) + { + // close the interface + result = (*(IOHIDDeviceInterface**) pDevice->interface)->close (pDevice->interface); + if (kIOReturnNotOpen == result) + { + // do nothing as device was not opened, thus can't be closed + } + else if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDCloseReleaseInterface - Failed to close IOHIDDeviceInterface.", result); + //release the interface + result = (*(IOHIDDeviceInterface**) pDevice->interface)->Release (pDevice->interface); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDCloseReleaseInterface - Failed to release interface.", result); + pDevice->interface = NULL; + } + return result; +} + +// --------------------------------- +// Get the next event in the queue for a device +// elements or entire device should be queued prior to calling this with HIDQueueElement or HIDQueueDevice +// returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise +// Note: kIOReturnUnderrun returned from getNextEvent indicates an empty queue not an error condition +// Note: application should pass in a pointer to a IOHIDEventStruct cast to a void (for CFM compatibility) + +unsigned char HIDGetEvent (pRecDevice pDevice, void * pHIDEvent) +{ + IOReturn result = kIOReturnBadArgument; + AbsoluteTime zeroTime = {0,0}; + + if (HIDIsValidDevice(pDevice)) + { + if (pDevice->queue) + { + result = (*(IOHIDQueueInterface**) pDevice->queue)->getNextEvent (pDevice->queue, (IOHIDEventStruct *)pHIDEvent, zeroTime, 0); + if (kIOReturnUnderrun == result) + return false; // no events in queue not an error per say + else if (kIOReturnSuccess != result) // actual error versus just an empty queue + HIDREPORTERRORNUM ("HIDGetEvent - Could not get HID event via getNextEvent.", result); + else + return true; + } + else + HIDREPORTERROR ("HIDGetEvent - queue does not exist."); + } + else + HIDREPORTERROR ("HIDGetEvent - invalid device."); + + return false; // did not get event +} + +// --------------------------------- +// returns current value for element, polling element +// will return 0 on error conditions which should be accounted for by application + +long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement) +{ + IOReturn result = kIOReturnBadArgument; + IOHIDEventStruct hidEvent; + + hidEvent.value = 0; + hidEvent.longValueSize = 0; + hidEvent.longValue = nil; + + if (HIDIsValidElement(pDevice, pElement)) + { + if (NULL != pDevice->interface) + { + // ++ NOTE: If the element type is feature then use queryElementValue instead of getElementValue + if (kIOHIDElementTypeFeature == pElement->type) + { + result = (*(IOHIDDeviceInterface**) pDevice->interface)->queryElementValue (pDevice->interface, pElement->cookie, &hidEvent,0,NULL,NULL,NULL); + if (kIOReturnUnsupported == result) // unless it's unsuported. + goto try_getElementValue; + else if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDGetElementValue - Could not get HID element value via queryElementValue.", result); + } + else if (pElement->type <= kIOHIDElementTypeInput_ScanCodes) + { +try_getElementValue: + result = (*(IOHIDDeviceInterface**) pDevice->interface)->getElementValue (pDevice->interface, pElement->cookie, &hidEvent); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDGetElementValue - Could not get HID element value via getElementValue.", result); + } + // on 10.0.x this returns the incorrect result for negative ranges, so fix it!!! + // this is not required on Mac OS X 10.1+ + if ((pElement->min < 0) && (hidEvent.value > pElement->max)) // assume range problem + hidEvent.value = hidEvent.value + pElement->min - pElement->max - 1; + } + else + HIDREPORTERROR ("HIDGetElementValue - no interface for device."); + } + else + HIDREPORTERROR ("HIDGetElementValue - invalid device and/or element."); + + // record min and max for auto scale and auto ... + if (hidEvent.value < pElement->calMin) + pElement->calMin = hidEvent.value; + if (hidEvent.value > pElement->calMax) + pElement->calMax = hidEvent.value; + + // auto user scale + return hidEvent.value; +} + +// --------------------------------- +// Set an elements value +// NOTE: This should only be used when a single element of a report needs to be sent. +// If multiple elements are to be send then transactions should be used. + +long HIDSetElementValue (pRecDevice pDevice, pRecElement pElement,void* pIOHIDEvent) +{ + IOHIDEventStruct* pMyIOHIDEvent = (IOHIDEventStruct*) pIOHIDEvent; + IOReturn result = kIOReturnError; // assume failure (pessimist!) + + if (HIDIsValidElement(pDevice, pElement)) + { + if (NULL != pDevice->interface) + { + result = (*(IOHIDDeviceInterface**) pDevice->interface)->setElementValue (pDevice->interface, pElement->cookie, pMyIOHIDEvent, -1, nil, nil, nil); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDSetElementValue - Could not set HID element value via setElementValue.", result); + } + else + HIDREPORTERROR ("HIDSetElementValue - no interface for device."); + } + else + HIDREPORTERROR ("HIDSetElementValue - invalid device and/or element."); + + return result; +} + +// --------------------------------- +// Set a callback to be called when a queue goes from empty to non-empty +long HIDSetQueueCallback (pRecDevice pDevice, IOHIDCallbackFunction callback) +{ + IOReturn result = kIOReturnError; // assume failure (pessimist!) + + if (HIDIsValidDevice(pDevice)) + { +#if USE_ASYNC_EVENTS + // if we don't have a queue runloop sourceÉ + if (NULL == pDevice->queueRunLoopSource) + { + // then create one + result = (*(IOHIDQueueInterface**) pDevice->queue)->createAsyncEventSource((void *) pDevice->queue, + (CFRunLoopSourceRef*) &pDevice->queueRunLoopSource); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDSetQueueCallback - Failed to createAsyncEventSource error: ", result); + } + // if we have one nowÉ + if (NULL != pDevice->queueRunLoopSource) + { + // and it's not already attached to our runloopÉ + if (!CFRunLoopContainsSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode)) + // then attach it now. + CFRunLoopAddSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode); + } + + // now install our callback + result = (*(IOHIDQueueInterface**) pDevice->queue)->setEventCallout(pDevice->queue, callback, pDevice, pDevice); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDSetQueueCallback - Could not set HID queue callback via setEventCallout.", result); +#endif USE_ASYNC_EVENTS + } + else + HIDREPORTERROR ("HIDSetQueueCallback - invalid device and/or element."); + return result; +} + +#if 1 +// --------------------------------- +// Get a report from a device +long HIDGetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, UInt32* reportBufferSize) +{ + IOReturn result = kIOReturnError; // assume failure (pessimist!) + + if (HIDIsValidDevice(pDevice)) + { + if (NULL != pDevice->interface) + { + result = (*(IOHIDDeviceInterface**) pDevice->interface)->getReport (pDevice->interface, reportType, reportID, reportBuffer, reportBufferSize, -1, nil, nil, nil); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDGetReport - Could not getReport, error: ", result); + } + else + HIDREPORTERROR ("HIDGetReport - no interface for device."); + } + else + HIDREPORTERROR ("HIDGetReport - invalid device."); + + return result; +} + +// --------------------------------- +// Send a report to a device +long HIDSetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, const UInt32 reportBufferSize) +{ + IOReturn result = kIOReturnError; // assume failure (pessimist!) + + if (HIDIsValidDevice(pDevice)) + { + if (NULL != pDevice->interface) + { + result = (*(IOHIDDeviceInterface**) pDevice->interface)->setReport (pDevice->interface, reportType, reportID, reportBuffer, reportBufferSize, -1, nil, nil, nil); + if (kIOReturnSuccess != result) + HIDREPORTERRORNUM ("HIDGetReport - Could not setReport; error: ", result); + } + else + HIDREPORTERROR ("HIDGetReport - no interface for device."); + } + else + HIDREPORTERROR ("HIDGetReport - invalid device."); + + return result; +} +#endif \ No newline at end of file diff --git a/HID_Queue_Utilities.h b/HID_Queue_Utilities.h new file mode 100755 index 0000000..e9b0501 --- /dev/null +++ b/HID_Queue_Utilities.h @@ -0,0 +1,114 @@ +/* + File: HID_Queue_Utilities.h + + Contains: Definition of the HID queue functions for the HID utilites. + + DRI: George Warner + + Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _HID_Queue_Utilities_h_ +#define _HID_Queue_Utilities_h_ + +#include "HID_Utilities.h" + +// ================================== + +#ifdef __cplusplus +extern "C" { +#endif + +// ================================== + +enum +{ + kDeviceQueueSize = 50 // this is wired kernel memory so should be set to as small as possible + // but should account for the maximum possible events in the queue + // USB updates will likely occur at 100 Hz so one must account for this rate of + // if states change quickly (updates are only posted on state changes) +}; + +// ================================== +// queues specific element, performing any device queue set up required +extern unsigned long HIDQueueElement (pRecDevice pDevice, pRecElement pElement); + +// adds all elements to queue, performing any device queue set up required +extern unsigned long HIDQueueDevice (pRecDevice pDevice); + +// removes element for queue, if last element in queue will release queue and device +extern unsigned long HIDDequeueElement (pRecDevice pDevice, pRecElement pElement); + +// completely removes all elements from queue and releases queue and device +extern unsigned long HIDDequeueDevice (pRecDevice pDevice); + +// releases all device queues for quit or rebuild (must be called) +extern unsigned long HIDReleaseAllDeviceQueues (void); + +// releases interface to device, should be done prior to exiting application (called from HIDReleaseDeviceList) +extern unsigned long HIDCloseReleaseInterface (pRecDevice pDevice); + +// returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise +// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned char HIDGetEvent (pRecDevice pDevice, void * pHIDEvent); + +// returns current value for element, creating device interface as required, polling element +extern long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement); + +// Set an elements value +// NOTE: This should only be used when a single element report needs to be sent. +// If multiple elements reports are to be send then transactions should be used. +extern long HIDSetElementValue (pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pIOHIDEvent); + +// Set a callback to be called when a queue goes from empty to non-empty +extern long HIDSetQueueCallback (pRecDevice pDevice, IOHIDCallbackFunction callback); + +#if 0 +// Get a report from a device +extern long HIDGetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, UInt32* reportBufferSize); + +// Send a report to a device +extern long HIDSetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, const UInt32 reportBufferSize); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // _HID_Queue_Utilities_h_ + diff --git a/HID_Transaction_Utilities.c b/HID_Transaction_Utilities.c new file mode 100755 index 0000000..c9012f1 --- /dev/null +++ b/HID_Transaction_Utilities.c @@ -0,0 +1,316 @@ +/* + File: HID_Transaction_Utilities.h + + Contains: Definitions of the HID queue functions for the HID utilites. + + DRI: George Warner + + Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "HID_Utilities_Internal.h" +#include "HID_Utilities_External.h" + +// ================================== +// private functions + +// creates a transaction for a device, allocates and creates the transaction interface if required + +static IOReturn hid_CreateTransaction(pRecDevice pDevice) +{ + IOReturn result = kIOReturnSuccess; + + if (HIDIsValidDevice(pDevice)) + { + if (NULL == pDevice->transaction) // if we don't already have a transactionÉ + { + if (NULL != pDevice->interface) // and we do have an interfaceÉ + { + pDevice->transaction = (void *) (*(IOHIDDeviceInterface**) pDevice->interface)->allocOutputTransaction (pDevice->interface); // alloc Transaction + if (pDevice->transaction) // if it was successfulÉ + { + result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->create (pDevice->transaction); // create actual transaction + if (kIOReturnSuccess != result) + HIDReportErrorNum ("\nFailed to create transaction via create: error = %ld.", result); + } + else + { + HIDReportError ("\nhid_CreateTransaction failed to allocOutputTransaction"); + if (!result) + result = kIOReturnError; // synthesis error + } + } + else + HIDReportErrorNum ("\nhid_CreateTransaction failed: Device inteface does not exist.", result); + } + } + return result; +} + +// ================================== +// public functions +// --------------------------------- +// add an element to a Transaction +unsigned long HIDTransactionAddElement(pRecDevice pDevice, pRecElement pElement) +{ + IOReturn result = hid_CreateTransaction(pDevice); + + if (HIDIsValidElement(pDevice,pElement)) + { + if (pDevice->transaction) + { + result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->addElement (pDevice->transaction,pElement->cookie); // add element + if (kIOReturnSuccess != result) + HIDReportErrorNum ("\nHIDTransactionAddElement failed to add Element: error = %ld.", result); + } + else + { + HIDReportError ("\nHIDTransactionAddElement failed: no transaction interface"); + if (!result) + result = kIOReturnError; // synthesis error + } + } + return result; +} + +// removes an element from a Transaction +unsigned long HIDTransactionRemoveElement(pRecDevice pDevice, pRecElement pElement) +{ + IOReturn result = hid_CreateTransaction(pDevice); + + if (HIDIsValidElement(pDevice,pElement)) + { + if (pDevice->transaction) + { + result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->removeElement (pDevice->transaction,pElement->cookie); // remove element + if (kIOReturnSuccess != result) + HIDReportErrorNum ("\nHIDTransactionRemoveElement failed to remove Element: error = %ld.", result); + } + else + { + HIDReportError ("\nHIDTransactionRemoveElement failed: no transaction interface"); + if (!result) + result = kIOReturnError; // synthesis error + } + } + + return result; +} + +// return true if this transaction contains this element +Boolean HIDTransactionHasElement(pRecDevice pDevice, pRecElement pElement) +{ + Boolean result = false; + + if (HIDIsValidElement(pDevice,pElement)) + { + (void) hid_CreateTransaction(pDevice); + + if (pDevice->transaction) + { + result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->hasElement (pDevice->transaction,pElement->cookie); // remove element + } + else + { + HIDReportError ("\nHIDTransactionHasElement failed: no transaction interface"); + } + } + return result; +} + +/* This changes the default value of an element, when the values of the */ +/* elements are cleared, on clear or commit, they are reset to the */ +/* default value */ +/* This call can be made on elements that are not in the transaction, but */ +/* has undefined behavior if made on elements not in the transaction */ +/* which are later added to the transaction. */ +/* In other words, an element should be added before its default is */ +/* set, for well defined behavior. */ +unsigned long HIDTransactionSetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent) +{ + IOReturn result = hid_CreateTransaction(pDevice); + + if (HIDIsValidElement(pDevice,pElement)) + { + if (pDevice->transaction) + { + result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->setElementDefault (pDevice->transaction,pElement->cookie, pValueEvent); + if (kIOReturnSuccess != result) + HIDReportErrorNum ("\nHIDTransactionSetElementDefault failed to set Element Default: error = %ld.", result); + } + else + { + HIDReportError ("\nHIDTransactionSetElementDefault failed: no transaction interface"); + if (!result) + result = kIOReturnError; // synthesis error + } + } + + return result; +} + +/* Get the current setting of an element's default value */ +unsigned long HIDTransactionGetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent) +{ + IOReturn result = hid_CreateTransaction(pDevice); + + if (HIDIsValidElement(pDevice,pElement)) + { + if (pDevice->transaction) + { + result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->getElementDefault (pDevice->transaction,pElement->cookie, pValueEvent); + if (kIOReturnSuccess != result) + HIDReportErrorNum ("\nHIDTransactionGetElementDefault failed to get Element Default: error = %ld.", result); + } + else + { + HIDReportError ("\nHIDTransactionGetElementDefault failed: no transaction interface"); + if (!result) + result = kIOReturnError; // synthesis error + } + } + return result; +} + +/* Add a change to the transaction, by setting an element value */ +/* The change is not actually made until it is commited */ +/* The element must be part of the transaction or this call will fail */ +unsigned long HIDTransactionSetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent) +{ + IOReturn result = hid_CreateTransaction(pDevice); + + if (HIDIsValidElement(pDevice,pElement)) + { + if (pDevice->transaction) + { + result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->setElementValue (pDevice->transaction,pElement->cookie, pValueEvent); + if (kIOReturnSuccess != result) + HIDReportErrorNum ("\nHIDTransactionSetElementValue failed to set Element Default: error = %ld.", result); + } + else + { + HIDReportError ("\nHIDTransactionSetElementValue failed: no transaction interface"); + if (!result) + result = kIOReturnError; // synthesis error + } + } + return result; +} + +/* Get the current setting of an element value */ +unsigned long HIDTransactionGetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent) +{ + IOReturn result = hid_CreateTransaction(pDevice); + + if (HIDIsValidElement(pDevice,pElement)) + { + if (pDevice->transaction) + { + result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->getElementValue (pDevice->transaction,pElement->cookie, pValueEvent); + if (kIOReturnSuccess != result) + HIDReportErrorNum ("\nHIDTransactionGetElementValue failed to get Element Default: error = %ld.", result); + } + else + { + HIDReportError ("\nHIDTransactionGetElementValue failed: no transaction interface"); + if (!result) + result = kIOReturnError; // synthesis error + } + } + return result; +} + +/* Commit the transaction, or clear all the changes and start over */ +unsigned long HIDTransactionCommit(pRecDevice pDevice) +{ + IOReturn result = hid_CreateTransaction(pDevice); + + if (HIDIsValidDevice(pDevice)) + { + if (pDevice->transaction) + { +#if 0000 + // NOTE: this code is to workaround a bug where if you commit transactions + // too fast then some of the reports get dropped. + // (fixed in 10.2.1) + static AbsoluteTime nextTime = {0,0}; // first time this should be no delay + + if (nextTime.hi || nextTime.lo) + MPDelayUntil(&nextTime); +#endif + result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->commit (pDevice->transaction,-1,NULL,NULL,NULL); + if (kIOReturnSuccess != result) + HIDReportErrorNum ("\nHIDTransactionCommit failed to commit: error = %ld.", result); +#if 0000 + nextTime = AddDurationToAbsolute(20 * kDurationMillisecond,UpTime()); +#endif + } + else + { + HIDReportError ("\nHIDTransactionCommit failed: no transaction interface"); + if (!result) + result = kIOReturnError; // synthesis error + } + } + return result; +} + +/* Clear all the changes and start over */ +unsigned long HIDTransactionClear(pRecDevice pDevice) +{ + IOReturn result = hid_CreateTransaction(pDevice); + + if (HIDIsValidDevice(pDevice)) + { + if (pDevice->transaction) + { + result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->clear (pDevice->transaction); + if (kIOReturnSuccess != result) + HIDReportErrorNum ("\nHIDTransactionClear failed to get Element Default: error = %ld.", result); + } + else + { + HIDReportError ("\nHIDTransactionClear failed: no transaction interface"); + if (!result) + result = kIOReturnError; // synthesis error + } + } + return result; +} diff --git a/HID_Utilities.c b/HID_Utilities.c new file mode 100755 index 0000000..7d74712 --- /dev/null +++ b/HID_Utilities.c @@ -0,0 +1,2197 @@ +/* + File: HID_Utilities.c + + Contains: Implementation of HID Utilities + + DRI: George Warner + + Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "HID_Utilities_Internal.h" +#include "HID_Utilities_External.h" + +#include +#include +#include +#include + +//================================================================================================ +#define USE_NOTIFICATIONS 0 +//================================================================================================ +// local (static) functions +//================================================================================================ +static void hid_GetCollectionElements (CFMutableDictionaryRef deviceProperties, pRecElement *ppCurrentCollection); +static pRecDevice hid_DisposeDevice (pRecDevice ppDevice); +//================================================================================================ +// globals +//================================================================================================ +#if USE_NOTIFICATIONS +static IONotificationPortRef gNotifyPort; +static io_iterator_t gAddedIter; +static CFRunLoopRef gRunLoop; +#endif USE_NOTIFICATIONS + +// for element retrieval +static pRecDevice gCurrentGetDevice = NULL; +static Boolean gAddAsChild = false; +static int gDepth = false; + +static pRecDevice gpDeviceList = NULL; +static UInt32 gNumDevices = 0; + +#pragma mark private functions +// ================================== +// private functions + +static UInt32 hid_CountCurrentDevices (void); + +// extracts actual specific element information from each element CF dictionary entry +static void hid_GetElementInfo (CFTypeRef refElement, pRecElement pElement) +{ + long number; + CFTypeRef refType; + // type, usagePage, usage already stored + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementCookieKey)); + if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) + pElement->cookie = (IOHIDElementCookie) number; + else + pElement->cookie = (IOHIDElementCookie) 0; + + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMinKey)); + if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) + pElement->min = number; + else + pElement->min = 0; + + pElement->calMax = pElement->min; + pElement->userMin = kDefaultUserMin; + + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMaxKey)); + if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) + pElement->max = number; + else + pElement->max = 0; + + pElement->calMin = pElement->max; + pElement->userMax = kDefaultUserMax; + + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMinKey)); + if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) + pElement->scaledMin = number; + else + pElement->scaledMin = 0; + + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMaxKey)); + if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) + pElement->scaledMax = number; + else + pElement->scaledMax = 0; + + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementSizeKey)); + if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) + pElement->size = number; + else + pElement->size = 0; + + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsRelativeKey)); + if (refType) + pElement->relative = CFBooleanGetValue (refType); + else + pElement->relative = 0; + + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsWrappingKey)); + if (refType) + pElement->wrapping = CFBooleanGetValue (refType); + else + pElement->wrapping = false; + + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsNonLinearKey)); + if (refType) + pElement->nonLinear = CFBooleanGetValue (refType); + else + pElement->wrapping = false; + +#ifdef kIOHIDElementHasPreferredStateKey + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasPreferredStateKey)); +#else // Mac OS X 10.0 has spelling error + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasPreferedStateKey)); +#endif + if (refType) + pElement->preferredState = CFBooleanGetValue (refType); + else + pElement->preferredState = false; + + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasNullStateKey)); + if (refType) + pElement->nullState = CFBooleanGetValue (refType); + else + pElement->nullState = false; + + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUnitKey)); + if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) + pElement->units = number; + else + pElement->units = 0; + + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUnitExponentKey)); + if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) + pElement->unitExp = number; + else + pElement->unitExp = 0; + + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementNameKey)); + if (refType) + if (!CFStringGetCString (refType, pElement->name, 256, CFStringGetSystemEncoding ())) + HIDReportError ("CFStringGetCString error retrieving pElement->name."); + if (!*pElement->name) + { + // set name from vendor id, product id & usage info look up + if (!HIDGetElementNameFromVendorProductUsage (gCurrentGetDevice->vendorID, gCurrentGetDevice->productID, pElement->usagePage, pElement->usage, pElement->name)) + { + // set name from vendor id/product id look up + HIDGetElementNameFromVendorProductCookie (gCurrentGetDevice->vendorID, gCurrentGetDevice->productID, (long) pElement->cookie, pElement->name); + if (!*pElement->name) { // if no name + HIDGetUsageName (pElement->usagePage, pElement->usage, pElement->name); + if (!*pElement->name) // if not usage + sprintf (pElement->name, "Element"); + } + } + } +} + +// --------------------------------- +// examines CF dictionary vlaue in device element hierarchy to determine if it is element of interest or a collection of more elements +// if element of interest allocate storage, add to list and retrieve element specific info +// if collection then pass on to deconstruction collection into additional individual elements + +static void hid_AddElement (CFTypeRef refElement, pRecElement * ppElementCurrent) +{ + pRecDevice pDevice = gCurrentGetDevice; + pRecElement pElement = NULL; + long elementType, usagePage, usage; + CFTypeRef refElementType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementTypeKey)); + CFTypeRef refUsagePage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsagePageKey)); + CFTypeRef refUsage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsageKey)); + + if (refElementType) + CFNumberGetValue (refElementType, kCFNumberLongType, &elementType); + if (refUsagePage) + CFNumberGetValue (refUsagePage, kCFNumberLongType, &usagePage); + if (refUsage) + CFNumberGetValue (refUsage, kCFNumberLongType, &usage); + + if (NULL == pDevice) + return; + + if (elementType) + { + // look at types of interest + if (elementType != kIOHIDElementTypeCollection) + { + if (usagePage && usage) // if valid usage and page + { + switch (usagePage) // only interested in kHIDPage_GenericDesktop and kHIDPage_Button + { + case kHIDPage_GenericDesktop: + { + switch (usage) // look at usage to determine function + { + case kHIDUsage_GD_X: + case kHIDUsage_GD_Y: + case kHIDUsage_GD_Z: + case kHIDUsage_GD_Rx: + case kHIDUsage_GD_Ry: + case kHIDUsage_GD_Rz: + pElement = (pRecElement) malloc (sizeof (recElement)); + if (pElement) pDevice->axis++; + break; + case kHIDUsage_GD_Slider: + pElement = (pRecElement) malloc (sizeof (recElement)); + if (pElement) pDevice->sliders++; + break; + case kHIDUsage_GD_Dial: + pElement = (pRecElement) malloc (sizeof (recElement)); + if (pElement) pDevice->dials++; + break; + case kHIDUsage_GD_Wheel: + pElement = (pRecElement) malloc (sizeof (recElement)); + if (pElement) pDevice->wheels++; + break; + case kHIDUsage_GD_Hatswitch: + pElement = (pRecElement) malloc (sizeof (recElement)); + if (pElement) pDevice->hats++; + break; + default: + pElement = (pRecElement) malloc (sizeof (recElement)); + break; + } + } + break; + case kHIDPage_Button: + pElement = (pRecElement) malloc (sizeof (recElement)); + if (pElement) pDevice->buttons++; + break; + default: + // just add a generic element + pElement = (pRecElement) malloc (sizeof (recElement)); + break; + } + } +#if 0 + else + HIDReportError ("CFNumberGetValue error when getting value for refUsage or refUsagePage."); +#endif 0 + } + else // collection + pElement = (pRecElement) malloc (sizeof (recElement)); + } + else + HIDReportError ("CFNumberGetValue error when getting value for refElementType."); + + if (pElement) // add to list + { + // this code builds a binary tree based on the collection hierarchy of inherent in the device element layout + // it preserves the structure of the lements as collections have children and elements are siblings to each other + + // clear record + bzero(pElement,sizeof(recElement)); + + // get element info + pElement->type = elementType; + pElement->usagePage = usagePage; + pElement->usage = usage; + pElement->depth = 0; // assume root object + hid_GetElementInfo (refElement, pElement); + + // count elements + pDevice->totalElements++; + + switch (pElement->type) + { + case kIOHIDElementTypeInput_Misc: + case kIOHIDElementTypeInput_Button: + case kIOHIDElementTypeInput_Axis: + case kIOHIDElementTypeInput_ScanCodes: + pDevice->inputs++; + break; + case kIOHIDElementTypeOutput: + pDevice->outputs++; + break; + case kIOHIDElementTypeFeature: + pDevice->features++; + break; + case kIOHIDElementTypeCollection: + pDevice->collections++; + break; + default: + HIDReportErrorNum ("Unknown element type : ", pElement->type); + } + + if (NULL == *ppElementCurrent) // if at list head + { + pDevice->pListElements = pElement; // add current element + *ppElementCurrent = pElement; // set current element to element we just added + } + else // have exsiting structure + { + if (gAddAsChild) // if the previous element was a collection, let's add this as a child of the previous + { + // this iteration should not be needed but there maybe some untested degenerate case which this code will ensure works + while ((*ppElementCurrent)->pChild) // step down tree until free child node found + *ppElementCurrent = (*ppElementCurrent)->pChild; + (*ppElementCurrent)->pChild = pElement; // insert there + pElement->depth = (*ppElementCurrent)->depth + 1; + } + else // add as sibling + { + // this iteration should not be needed but there maybe some untested degenerate case which this code will ensure works + while ((*ppElementCurrent)->pSibling) // step down tree until free sibling node found + *ppElementCurrent = (*ppElementCurrent)->pSibling; + (*ppElementCurrent)->pSibling = pElement; // insert there + pElement->depth = (*ppElementCurrent)->depth; + } + pElement->pPrevious = *ppElementCurrent; // point to previous + *ppElementCurrent = pElement; // set current to our collection + } + + if (elementType == kIOHIDElementTypeCollection) // if this element is a collection of other elements + { + gAddAsChild = true; // add next set as children to this element + gDepth++; + hid_GetCollectionElements ((CFMutableDictionaryRef) refElement, &pElement); // recursively process the collection + gDepth--; + } + gAddAsChild = false; // add next as this elements sibling (when return from a collection or with non-collections) + } +#if 0 + else + HIDReportError ("hid_AddElement - no element added."); +#endif +} + +// --------------------------------- +// collects information from each array member in device element list (each array memeber = element) + +static void hid_GetElementsCFArrayHandler (const void * value, void * parameter) +{ + if (CFGetTypeID (value) == CFDictionaryGetTypeID ()) + hid_AddElement ((CFTypeRef) value, (pRecElement *) parameter); +} + +// --------------------------------- +// handles retrieval of element information from arrays of elements in device IO registry information + +static void hid_GetElements (CFTypeRef refElementCurrent, pRecElement *ppCurrentElement) +{ + CFTypeID type = CFGetTypeID (refElementCurrent); + if (type == CFArrayGetTypeID()) // if element is an array + { + CFRange range = {0, CFArrayGetCount (refElementCurrent)}; + // CountElementsCFArrayHandler called for each array member + CFArrayApplyFunction (refElementCurrent, range, hid_GetElementsCFArrayHandler, ppCurrentElement); + } +} + +// --------------------------------- +// handles extracting element information from element collection CF types +// used from top level element decoding and hierarchy deconstruction to flatten device element list + +static void hid_GetCollectionElements (CFMutableDictionaryRef deviceProperties, pRecElement *ppCurrentCollection) +{ + CFTypeRef refElementTop = CFDictionaryGetValue (deviceProperties, CFSTR(kIOHIDElementKey)); + if (refElementTop) + hid_GetElements (refElementTop, ppCurrentCollection); + else + HIDReportError ("hid_GetCollectionElements: CFDictionaryGetValue error when creating CFTypeRef for kIOHIDElementKey."); +} + +// --------------------------------- +// use top level element usage page and usage to discern device usage page and usage setting appropriate values in device record + +static void hid_TopLevelElementHandler (const void * value, void * parameter) +{ + CFTypeRef refCF = 0; + if ((NULL == value) || (NULL == parameter)) + return; // (kIOReturnBadArgument) + if (CFGetTypeID (value) != CFDictionaryGetTypeID ()) + return; // (kIOReturnBadArgument) + refCF = CFDictionaryGetValue (value, CFSTR(kIOHIDElementUsagePageKey)); + if (!CFNumberGetValue (refCF, kCFNumberLongType, &((pRecDevice) parameter)->usagePage)) + HIDReportError ("CFNumberGetValue error retrieving pDevice->usagePage."); + refCF = CFDictionaryGetValue (value, CFSTR(kIOHIDElementUsageKey)); + if (!CFNumberGetValue (refCF, kCFNumberLongType, &((pRecDevice) parameter)->usage)) + HIDReportError ("CFNumberGetValue error retrieving pDevice->usage."); +} + +// --------------------------------- +// extracts device info from CF dictionary records in IO registry + +static void hid_GetDeviceInfo (io_object_t hidDevice, CFMutableDictionaryRef hidProperties, pRecDevice pDevice) +{ + CFMutableDictionaryRef usbProperties = 0; + io_registry_entry_t parent1, parent2; + + // Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also + // get dictionary for usb properties: step up two levels and get CF dictionary for USB properties + if ((KERN_SUCCESS == IORegistryEntryGetParentEntry (hidDevice, kIOServicePlane, &parent1)) && + (KERN_SUCCESS == IORegistryEntryGetParentEntry (parent1, kIOServicePlane, &parent2)) && + (KERN_SUCCESS == IORegistryEntryCreateCFProperties (parent2, &usbProperties, kCFAllocatorDefault, kNilOptions))) + { + if (usbProperties) + { + CFTypeRef refCF = 0; + // get device info + // try hid dictionary first, if fail then go to usb dictionary + + // get transport + refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDTransportKey)); + if (refCF) + { + if (!CFStringGetCString (refCF, pDevice->transport, 256, CFStringGetSystemEncoding ())) + HIDReportError ("CFStringGetCString error retrieving pDevice->transport."); + } + + // get vendorID + refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDVendorIDKey)); + if (!refCF) + refCF = CFDictionaryGetValue (usbProperties, CFSTR("idVendor")); + if (refCF) + { + if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->vendorID)) + HIDReportError ("CFNumberGetValue error retrieving pDevice->vendorID."); + } + + // get product ID + refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDProductIDKey)); + if (!refCF) + refCF = CFDictionaryGetValue (usbProperties, CFSTR("idProduct")); + if (refCF) + { + if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->productID)) + HIDReportError ("CFNumberGetValue error retrieving pDevice->productID."); + } + + // get product version + refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDVersionNumberKey)); + if (refCF) + { + if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->version)) + HIDReportError ("CFNumberGetValue error retrieving pDevice->version."); + } + + // get manufacturer name + refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDManufacturerKey)); + if (!refCF) + refCF = CFDictionaryGetValue (usbProperties, CFSTR("USB Vendor Name")); + if (refCF) + { + if (!CFStringGetCString (refCF, pDevice->manufacturer, 256, CFStringGetSystemEncoding ())) + HIDReportError ("CFStringGetCString error retrieving pDevice->manufacturer."); + } + + // get product name + refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDProductKey)); + if (!refCF) + refCF = CFDictionaryGetValue (usbProperties, CFSTR("USB Product Name")); + if (refCF) + { + if (!CFStringGetCString (refCF, pDevice->product, 256, CFStringGetSystemEncoding ())) + HIDReportError ("CFStringGetCString error retrieving pDevice->product."); + } + + // get serial + refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDSerialNumberKey)); + if (refCF) + { + if (!CFStringGetCString (refCF, pDevice->serial, 256, CFStringGetSystemEncoding ())) + HIDReportError ("CFStringGetCString error retrieving pDevice->serial."); + } + + // get location ID + refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDLocationIDKey)); + if (!refCF) + refCF = CFDictionaryGetValue (usbProperties, CFSTR("locationID")); + if (refCF) + { + if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->locID)) + HIDReportError ("CFNumberGetValue error retrieving pDevice->locID."); + } + + // get usage page and usage + refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsagePageKey)); + if (refCF) + { + if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usagePage)) + HIDReportError ("CFNumberGetValue error retrieving pDevice->usagePage."); + refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsageKey)); + if (refCF) + if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usage)) + HIDReportError ("CFNumberGetValue error retrieving pDevice->usage."); + } + if (NULL == refCF) // get top level element HID usage page or usage + { + // use top level element instead + CFTypeRef refCFTopElement = 0; + refCFTopElement = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDElementKey)); + { + // refCFTopElement points to an array of element dictionaries + CFRange range = {0, CFArrayGetCount (refCFTopElement)}; + CFArrayApplyFunction (refCFTopElement, range, hid_TopLevelElementHandler, NULL); + } + } + } + else + HIDReportError ("IORegistryEntryCreateCFProperties failed to create usbProperties."); + + CFRelease (usbProperties); + if (kIOReturnSuccess != IOObjectRelease (parent2)) + HIDReportError ("IOObjectRelease error with parent2."); + if (kIOReturnSuccess != IOObjectRelease (parent1)) + HIDReportError ("IOObjectRelease error with parent1."); + } +} + +// --------------------------------- +// adds device to linked list of devices passed in (handles NULL lists properly) +// (returns where you just stored it) +static pRecDevice* hid_AddDevice (pRecDevice *ppListDeviceHead, pRecDevice pNewDevice) +{ + pRecDevice* result = NULL; + + if (NULL == *ppListDeviceHead) + result = ppListDeviceHead; + else + { + pRecDevice pDevicePrevious = NULL, pDevice = *ppListDeviceHead; + while (pDevice) + { + pDevicePrevious = pDevice; + pDevice = pDevicePrevious->pNext; + } + result = &pDevicePrevious->pNext; + } + pNewDevice->pNext = NULL; + + *result = pNewDevice; + + return result; +} + +// --------------------------------- +// given a IO device object build a flat device record including device info and elements + +static pRecDevice hid_BuildDevice (io_object_t hidDevice) +{ + pRecDevice pDevice = (pRecDevice) malloc (sizeof (recDevice)); + + if (NULL != pDevice) + { + // get dictionary for HID properties + CFMutableDictionaryRef hidProperties = 0; + kern_return_t result = IORegistryEntryCreateCFProperties (hidDevice, &hidProperties, kCFAllocatorDefault, kNilOptions); + + // clear record + bzero(pDevice, sizeof(recDevice)); + + if ((result == KERN_SUCCESS) && (NULL != hidProperties)) + { + pRecElement pCurrentElement = NULL; + // create device interface + result = HIDCreateOpenDeviceInterface (hidDevice, pDevice); + if (kIOReturnSuccess != result) + HIDReportErrorNum ("HIDCreateOpenDeviceInterface failed.", result); + hid_GetDeviceInfo (hidDevice, hidProperties, pDevice); // hidDevice used to find parents in registry tree + // set current device for use in getting elements + gCurrentGetDevice = pDevice; + // Add all elements + hid_GetCollectionElements (hidProperties, &pCurrentElement); + gCurrentGetDevice = NULL; + CFRelease (hidProperties); + } + else + HIDReportErrorNum ("IORegistryEntryCreateCFProperties error when creating deviceProperties.", result); + } + else + HIDReportError ("malloc error when allocating pRecDevice."); + return pDevice; +} + +#if USE_NOTIFICATIONS +//================================================================================================ +// +// hid_DeviceNotification +// +// This routine will get called whenever any kIOGeneralInterest notification happens. We are +// interested in the kIOMessageServiceIsTerminated message so that's what we look for. Other +// messages are defined in IOMessage.h. +// +//================================================================================================ +// +static void hid_DeviceNotification( void *refCon, + io_service_t service, + natural_t messageType, + void *messageArgument ) +{ + pRecDevice pDevice = (pRecDevice) refCon; + + if (messageType == kIOMessageServiceIsTerminated) + { + printf("Device 0x%08x \"%s\"removed.\n", service, pDevice->product); + + // Free the data we're no longer using now that the device is going away + hid_DisposeDevice (pDevice); + } +} +#else + +static void hid_RemovalCallbackFunction(void * target, IOReturn result, void * refcon, void * sender) +{ + hid_DisposeDevice ((pRecDevice) target); +} + +#endif USE_NOTIFICATIONS + +//================================================================================================ +// +// hid_AddDevices +// +// This routine is the callback for our IOServiceAddMatchingNotification. When we get called +// we will look at all the devices that were added and we will: +// +// 1. Create some private data to relate to each device. +// 2. Submit an IOServiceAddInterestNotification of type kIOGeneralInterest for this device, +// using the refCon field to store a pointer to our data. When we get called with +// this interest notification, we can grab the refCon and access our private data. +// +//================================================================================================ +// +// --------------------------------- +// given a IO device iterator, iterate it and add all its devices + +static void hid_AddDevices (void *refCon, io_iterator_t iterator) +{ + // NOTE: refcon passed in is used to point to the device list head + pRecDevice* pListDeviceHead = (pRecDevice*) refCon; + IOReturn result = kIOReturnSuccess; + io_object_t ioHIDDeviceObject = 0; + + while (ioHIDDeviceObject = IOIteratorNext (iterator)) + { + pRecDevice* pNewDeviceAt = NULL; + pRecDevice pNewDevice = hid_BuildDevice (ioHIDDeviceObject); + if (pNewDevice) + { +#if 0 // set true for verbose output + printf("\nhid_AddDevices: pNewDevice = {t: \"%s\", v: %ld, p: %ld, v: %ld, m: \"%s\", " \ + "p: \"%s\", l: %ld, u: %4.4lX:%4.4lX, #e: %ld, #f: %ld, #i: %ld, #o: %ld, " \ + "#c: %ld, #a: %ld, #b: %ld, #h: %ld, #s: %ld, #d: %ld, #w: %ld}.", + pNewDevice->transport, + pNewDevice->vendorID, + pNewDevice->productID, + pNewDevice->version, + pNewDevice->manufacturer, + pNewDevice->product, + pNewDevice->locID, + pNewDevice->usagePage, + pNewDevice->usage, + pNewDevice->totalElements, + pNewDevice->features, + pNewDevice->inputs, + pNewDevice->outputs, + pNewDevice->collections, + pNewDevice->axis, + pNewDevice->buttons, + pNewDevice->hats, + pNewDevice->sliders, + pNewDevice->dials, + pNewDevice->wheels + ); + fflush(stdout); +#elif 0 // otherwise output brief description + printf("\nhid_AddDevices: pNewDevice = {m: \"%s\" p: \"%s\", vid: %ld, pid: %ld, loc: %8.8lX, usage: %4.4lX:%4.4lX}.", + pNewDevice->manufacturer, + pNewDevice->product, + pNewDevice->vendorID, + pNewDevice->productID, + pNewDevice->locID, + pNewDevice->usagePage, + pNewDevice->usage + ); + fflush(stdout); +#endif + pNewDeviceAt = hid_AddDevice (pListDeviceHead, pNewDevice); + } + +#if USE_NOTIFICATIONS + // Register for an interest notification of this device being removed. Use a reference to our + // private data as the refCon which will be passed to the notification callback. + result = IOServiceAddInterestNotification( gNotifyPort, // notifyPort + ioHIDDeviceObject, // service + kIOGeneralInterest, // interestType + hid_DeviceNotification, // callback + pNewDevice, // refCon + (io_object_t*) &pNewDevice->notification); // notification + if (KERN_SUCCESS != result) + HIDReportErrorNum ("hid_AddDevices: IOServiceAddInterestNotification error: x0%8.8lX.", result); +#else + result = (*(IOHIDDeviceInterface**)pNewDevice->interface)->setRemovalCallback (pNewDevice->interface, hid_RemovalCallbackFunction,pNewDeviceAt,0); +#endif USE_NOTIFICATIONS + + // release the device object, it is no longer needed + result = IOObjectRelease (ioHIDDeviceObject); + if (KERN_SUCCESS != result) + HIDReportErrorNum ("hid_AddDevices: IOObjectRelease error with ioHIDDeviceObject.", result); + } +} + +// --------------------------------- +// disposes of the element list associated with a device and the memory associated with the list +// uses depthwise recursion to dispose both collections and elements. + +static void hid_DisposeDeviceElements (pRecElement pElement) +{ + if (pElement) + { + if (pElement->pChild) + hid_DisposeDeviceElements (pElement->pChild); + if (pElement->pSibling) + hid_DisposeDeviceElements (pElement->pSibling); + free (pElement); + } +} + +// --------------------------------- +// disposes of a single device, closing and releaseing interface, freeing memory fro device and elements, setting device pointer to NULL +// all your device no longer belong to us... (i.e., you do not 'own' the device anymore) + +static pRecDevice hid_DisposeDevice (pRecDevice pDevice) +{ + kern_return_t result = KERN_SUCCESS; + pRecDevice pDeviceNext = NULL; + + if (HIDIsValidDevice(pDevice)) + { + // save next device prior to disposing of this device + pDeviceNext = pDevice->pNext; + + result = HIDDequeueDevice (pDevice); +#if 0 + if (kIOReturnSuccess != result) + HIDReportErrorNum ("hid_DisposeDevice: HIDDequeueDevice error: 0x%8.8X.", result); +#endif 1 + + hid_DisposeDeviceElements (pDevice->pListElements); + pDevice->pListElements = NULL; + + result = HIDCloseReleaseInterface (pDevice); // function sanity checks interface value (now application does not own device) + if (kIOReturnSuccess != result) + HIDReportErrorNum ("hid_DisposeDevice: HIDCloseReleaseInterface error: 0x%8.8X.", result); + +#if USE_NOTIFICATIONS + if (pDevice->interface) + { + // replace (*pDevice->interface)->Release(pDevice->interface); + result = IODestroyPlugInInterface (pDevice->interface); + if (kIOReturnSuccess != result) + HIDReportErrorNum ("hid_DisposeDevice: IODestroyPlugInInterface error: 0x%8.8X.", result); + } + + if (pDevice->notification) + { + result = IOObjectRelease((io_object_t) pDevice->notification); + if (kIOReturnSuccess != result) + HIDReportErrorNum ("hid_DisposeDevice: IOObjectRelease error: 0x%8.8X.", result); + } +#endif USE_NOTIFICATIONS + + // remove this device from the device list + if (gpDeviceList == pDevice) // head of list? + gpDeviceList = pDeviceNext; + else + { + pRecDevice pDeviceTemp = pDeviceNext = gpDeviceList; // we're going to return this if we don't find ourselfs in the list + while (pDeviceTemp) + { + if (pDeviceTemp->pNext == pDevice) // found us! + { + // take us out of linked list + pDeviceTemp->pNext = pDeviceNext = pDevice->pNext; + break; + } + pDeviceTemp = pDeviceTemp->pNext; + } + } + free (pDevice); + } + + // update device count + gNumDevices = hid_CountCurrentDevices (); + + return pDeviceNext; +} + +// --------------------------------- +// count number of devices in global device list (gpDeviceList) +static UInt32 hid_CountCurrentDevices (void) +{ + pRecDevice pDevice = gpDeviceList; + UInt32 devices = 0; + while (pDevice) + { + devices++; + pDevice = pDevice->pNext; + } + return devices; +} + +// --------------------------------- +// matches type masks passed in to actual element types (which are not set up to be used as a mask +static Boolean hid_MatchElementTypeMask (IOHIDElementType type, HIDElementTypeMask typeMask) +{ + if (typeMask & kHIDElementTypeInput) + if ((type == kIOHIDElementTypeInput_Misc) || (type == kIOHIDElementTypeInput_Button) || (type == kIOHIDElementTypeInput_Axis) || (type == kIOHIDElementTypeInput_ScanCodes)) + return true; + if (typeMask & kHIDElementTypeOutput) + if (type == kIOHIDElementTypeOutput) + return true; + if (typeMask & kHIDElementTypeFeature) + if (type == kIOHIDElementTypeFeature) + return true; + if (typeMask & kHIDElementTypeCollection) + if (type == kIOHIDElementTypeCollection) + return true; + return false; +} + +// --------------------------------- + +static pRecElement hid_GetDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask) +{ + // we are asking for this element + if (NULL != pElement) + { + if (hid_MatchElementTypeMask (pElement->type, typeMask)) // if the type match what we are looking for + return pElement; // return the element + else + return HIDGetNextDeviceElement (pElement, typeMask); // else get the next one + } + return NULL; +} + +#define FAKE_IT 0 // set true for debugging; returns the usage & usage page as numbers + +// --------------------------------- +// Load the usage strings from the resource (XML) file into a CFPropertyListRef +static CFPropertyListRef xml_load_usage_strings(void) +{ + CFPropertyListRef tCFPropertyListRef = NULL; + CFURLRef resFileCFURLRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("HID_usage_strings"), CFSTR("plist"), NULL); + + if (NULL != resFileCFURLRef) + { + CFDataRef resCFDataRef; + + if (CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, resFileCFURLRef, &resCFDataRef, nil, nil, nil)) + { + if (NULL != resCFDataRef) + { + CFStringRef errorString; + + tCFPropertyListRef = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resCFDataRef, kCFPropertyListImmutable, &errorString); + if (NULL == tCFPropertyListRef) + CFShow(errorString); + CFRelease(resCFDataRef); + } + } + CFRelease(resFileCFURLRef); + } + return tCFPropertyListRef; +} + +// --------------------------------- +// Find a usage string in the resource (XML) file + +static Boolean xml_GetUsageName(const long valueUsagePage, const long valueUsage, char* pCstr) +{ + static CFPropertyListRef tCFPropertyListRef = NULL; + Boolean results = false; + + if (NULL == tCFPropertyListRef) + tCFPropertyListRef = xml_load_usage_strings(); + if (NULL != tCFPropertyListRef) + { + if (CFDictionaryGetTypeID() == CFGetTypeID(tCFPropertyListRef)) + { + CFDictionaryRef pageCFDictionaryRef; + CFStringRef pageKeyCFStringRef; + pageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("0x%4.4lX"), valueUsagePage); + + if (CFDictionaryGetValueIfPresent(tCFPropertyListRef, pageKeyCFStringRef, (const void**) &pageCFDictionaryRef)) + { + CFStringRef pageCFStringRef; + + if (CFDictionaryGetValueIfPresent(pageCFDictionaryRef, CFSTR("Name"), (const void**) &pageCFStringRef)) + { + //CFShow(pageCFStringRef); + } + + { + CFStringRef fullCFStringRef = NULL; + CFStringRef usageKeyCFStringRef; + CFStringRef usageCFStringRef; + + usageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("0x%4.4lX"), valueUsage); + + if (CFDictionaryGetValueIfPresent(pageCFDictionaryRef, usageKeyCFStringRef, (const void**) &usageCFStringRef)) + { + fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@"), + pageCFStringRef, usageCFStringRef); + // CFShow(usageCFStringRef); + } +#if FAKE_IT + else + { + fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ #%@"), + pageCFStringRef, usageKeyCFStringRef); + } +#endif + if (fullCFStringRef) + { + // CFShow(fullCFStringRef); + results = CFStringGetCString( + fullCFStringRef, pCstr, CFStringGetLength(fullCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingMacRoman); + CFRelease(fullCFStringRef); + } + CFRelease(usageKeyCFStringRef); + } + } + CFRelease(pageKeyCFStringRef); + } + //++CFRelease(tCFPropertyListRef); // Leak this! + } + return results; +} + +#pragma mark public functions +// ================================= +// public functions + +// --------------------------------- +// Create and open an interface to device, required prior to extracting values or building queues +// Note: appliction now owns the device and must close and release it prior to exiting + +unsigned long HIDCreateOpenDeviceInterface (UInt32 hidDevice, pRecDevice pDevice) +{ + IOReturn result = kIOReturnSuccess; + HRESULT plugInResult = S_OK; + SInt32 score = 0; + IOCFPlugInInterface ** ppPlugInInterface = NULL; + + if (NULL == pDevice->interface) + { + result = IOCreatePlugInInterfaceForService (hidDevice, kIOHIDDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, &ppPlugInInterface, &score); + if (kIOReturnSuccess == result) + { + // Call a method of the intermediate plug-in to create the device interface + plugInResult = (*ppPlugInInterface)->QueryInterface (ppPlugInInterface, + CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID), (void *) &(pDevice->interface)); + if (S_OK != plugInResult) + HIDReportErrorNum ("CouldnÕt query HID class device interface from plugInInterface", plugInResult); + IODestroyPlugInInterface (ppPlugInInterface); // replace (*ppPlugInInterface)->Release (ppPlugInInterface) + } + else + HIDReportErrorNum ("Failed to create **plugInInterface via IOCreatePlugInInterfaceForService.", result); + } + if (NULL != pDevice->interface) + { + result = (*(IOHIDDeviceInterface**)pDevice->interface)->open (pDevice->interface, 0); + if (kIOReturnSuccess != result) + HIDReportErrorNum ("Failed to open pDevice->interface via open.", result); + } + return result; +} + +// --------------------------------- +// builds list of device with elements (allocates memory and captures devices) +// list is allcoated internally within HID Utilites and can be accessed via accessor functions +// structures within list are considered flat and user accessable, but not user modifiable +// can be called again to rebuild list to account for new devices (will do the right thing in case of disposing existing list) +// returns true if succesful + +Boolean HIDBuildDeviceList (UInt32 usagePage, UInt32 usage) +{ + IOReturn result = kIOReturnSuccess; + mach_port_t masterPort = 0; + if (NULL != gpDeviceList) + HIDReleaseDeviceList (); + + result = IOMasterPort (bootstrap_port, &masterPort); + if (kIOReturnSuccess != result) + HIDReportErrorNum ("IOMasterPort error with bootstrap_port.", result); + else + { + CFMutableDictionaryRef hidMatchDictionary = NULL; + + // Set up matching dictionary to search the I/O Registry for HID devices we are interested in. Dictionary reference is NULL if error. + { + CFNumberRef refUsage = NULL, refUsagePage = NULL; + + // Set up a matching dictionary to search I/O Registry by class name for all HID class devices. + hidMatchDictionary = IOServiceMatching (kIOHIDDeviceKey); + if (NULL != hidMatchDictionary) + { + if (usagePage) + { + // Add key for device type (joystick, in this case) to refine the matching dictionary. + refUsagePage = CFNumberCreate (kCFAllocatorDefault, kCFNumberLongType, &usagePage); + CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsagePageKey), refUsagePage); + CFRelease (refUsagePage); + if (usage) + { + refUsage = CFNumberCreate (kCFAllocatorDefault, kCFNumberLongType, &usage); + CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsageKey), refUsage); + CFRelease (refUsage); + } + } + CFRetain(hidMatchDictionary); + } + else + HIDReportError ("Failed to get HID CFMutableDictionaryRef via IOServiceMatching."); + } + +#if USE_NOTIFICATIONS + // Create a notification port and add its run loop event source to our run loop + // This is how async notifications get set up. + { + CFRunLoopSourceRef runLoopSource; + + gNotifyPort = IONotificationPortCreate(masterPort); + runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); + + gRunLoop = CFRunLoopGetCurrent(); + CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode); + + // Now set up a notification to be called when a device is first matched by I/O Kit. + result = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort + kIOFirstMatchNotification, // notificationType + hidMatchDictionary, // matching + hid_AddDevices, // callback + &gpDeviceList, // refCon + &gAddedIter // notification + ); + + // call it now to add all existing devices + hid_AddDevices(&gpDeviceList,gAddedIter); + } +#else + { + io_iterator_t hidObjectIterator = 0; + + // Now search I/O Registry for matching devices. + result = IOServiceGetMatchingServices (masterPort, hidMatchDictionary, &hidObjectIterator); + if (kIOReturnSuccess != result) + HIDReportErrorNum ("Failed to create IO object iterator, error:", result); + else if (NULL == hidObjectIterator) // likely no HID devices which matched selection criteria are connected + HIDReportError ("Warning: Could not find any matching devices, thus iterator creation failed."); + + if (0 != hidObjectIterator) + { + hid_AddDevices(&gpDeviceList,hidObjectIterator); + + result = IOObjectRelease (hidObjectIterator); // release the iterator + if (kIOReturnSuccess != result) + HIDReportErrorNum ("IOObjectRelease error with hidObjectIterator.", result); + + gNumDevices = hid_CountCurrentDevices (); + return true; + } + } +#endif USE_NOTIFICATIONS + // IOServiceGetMatchingServices consumes a reference to the dictionary, so we don't need to release the dictionary ref. + hidMatchDictionary = NULL; + } + return false; +} + +// --------------------------------- +// release list built by above function +// MUST be called prior to application exit to properly release devices +// if not called (or app crashes) devices can be recovered by pluging into different location in USB chain + +void HIDReleaseDeviceList (void) +{ + while (NULL != gpDeviceList) + gpDeviceList = hid_DisposeDevice (gpDeviceList); // dispose current device return next device will set gpDeviceList to NULL + gNumDevices = 0; +} + +// --------------------------------- +// does a device list exist + +Boolean HIDHaveDeviceList (void) +{ + if (NULL != gpDeviceList) + return true; + return false; +} + +// --------------------------------- +// how many HID devices have been found +// returns 0 if no device list exist + +UInt32 HIDCountDevices (void) +{ + gNumDevices = hid_CountCurrentDevices (); + + return gNumDevices; +} + +// --------------------------------- +// how many elements does a specific device have +// returns 0 if device is invlaid or NULL + +UInt32 HIDCountDeviceElements (pRecDevice pDevice, HIDElementTypeMask typeMask) +{ + long count = 0; + if (HIDIsValidDevice(pDevice)) + { + if (typeMask & kHIDElementTypeInput) + count += pDevice->inputs; + if (typeMask & kHIDElementTypeOutput) + count += pDevice->outputs; + if (typeMask & kHIDElementTypeFeature) + count += pDevice->features; + if (typeMask & kHIDElementTypeCollection) + count += pDevice->collections; + } + return count; +} + +// --------------------------------- +// get the first device in the device list +// returns NULL if no list exists + +pRecDevice HIDGetFirstDevice (void) +{ + return gpDeviceList; +} + +// --------------------------------- +// get next device in list given current device as parameter +// returns NULL if end of list + +pRecDevice HIDGetNextDevice (pRecDevice pDevice) +{ + if (NULL != pDevice) + return pDevice->pNext; + else + return NULL; +} + +// --------------------------------- +// get the first element of device passed in as parameter +// returns NULL if no list exists or device does not exists or is NULL +pRecElement HIDGetFirstDeviceElement (pRecDevice pDevice, HIDElementTypeMask typeMask) +{ + if (HIDIsValidDevice(pDevice)) + { + if (hid_MatchElementTypeMask (pDevice->pListElements->type, typeMask)) // ensure first type matches + return pDevice->pListElements; + else + return HIDGetNextDeviceElement (pDevice->pListElements, typeMask); + } + else + return NULL; +} + +// --------------------------------- +// get next element of given device in list given current element as parameter +// will walk down each collection then to next element or collection (depthwise traverse) +// returns NULL if end of list +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get previous HIDGetNextDeviceElement functionality +pRecElement HIDGetNextDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask) +{ + // should only have elements passed in (though someone could mix calls and pass us a collection) + // collection means return the next child or sibling (in that order) + // element means returnt he next sibling (as elements can't have children + if (NULL != pElement) + { + if (pElement->pChild) + { + if (pElement->type != kIOHIDElementTypeCollection) + HIDReportError ("Malformed element list: found child of element."); + else + return hid_GetDeviceElement (pElement->pChild, typeMask); // return the child of this element + } + else if (pElement->pSibling) + { + return hid_GetDeviceElement (pElement->pSibling, typeMask); //return the sibling of this element + } + else // at end back up correctly + { + pRecElement pPreviousElement = NULL; + // malformed device ending in collection + if (pElement->type == kIOHIDElementTypeCollection) + HIDReportError ("Malformed device: found collection at end of element chain."); + // walk back up tree to element prior to first collection ecountered and take next element + while (NULL != pElement->pPrevious) + { + pPreviousElement = pElement; + pElement = pElement->pPrevious; // look at previous element + // if we have a collection and the previous element is the branch element (should have both a colection and next element attached to it) + // if we found a collection, which we are not at the sibling level that actually does have siblings + if (((pElement->type == kIOHIDElementTypeCollection) && (pPreviousElement != pElement->pSibling) && pElement->pSibling) || + // or if we are at the top + (NULL == pElement->pPrevious)) // at top of tree + break; + } + if (NULL == pElement->pPrevious) + return NULL; // got to top of list with only a collection as the first element + // now we must have been down the child route so go down the sibling route + pElement = pElement->pSibling; // element of interest + return hid_GetDeviceElement (pElement, typeMask); // otherwise return this element + } + } + return NULL; +} + +// --------------------------------- +// get previous element of given device in list given current element as parameter +// this wlaks directly up the tree to the top element and does not search at each level +// returns NULL if beginning of list +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get non-collection elements +pRecElement HIDGetPreviousDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask) +{ + pRecElement pPreviousElement = pElement->pPrevious; + // walk back up tree to element prior + while (pPreviousElement && !hid_MatchElementTypeMask (pPreviousElement->type, typeMask)) + { + pElement = pPreviousElement; // look at previous element + pPreviousElement = pElement->pPrevious; + } + return pPreviousElement; // return this element +} + +// --------------------------------- +// returns C string type name given a type enumeration passed in as parameter (see IOHIDKeys.h) +// returns "Unknown Type" for invalid types + +void HIDGetTypeName (IOHIDElementType theType, char * cstrName) +{ + switch (theType) + { + case kIOHIDElementTypeInput_Misc: + sprintf(cstrName, "Miscellaneous Input"); + break; + case kIOHIDElementTypeInput_Button: + sprintf(cstrName, "Button Input"); + break; + case kIOHIDElementTypeInput_Axis: + sprintf(cstrName, "Axis Input"); + break; + case kIOHIDElementTypeInput_ScanCodes: + sprintf(cstrName, "Scan Code Input"); + break; + case kIOHIDElementTypeOutput: + sprintf(cstrName, "Output"); + break; + case kIOHIDElementTypeFeature: + sprintf(cstrName, "Feature"); + break; + case kIOHIDElementTypeCollection: + sprintf(cstrName, "Collection"); + break; + default: + sprintf(cstrName, "Unknown Type"); + break; + } +} + +// --------------------------------- +// returns C string usage given usage page and usage passed in as parameters (see IOUSBHIDParser.h) +// returns usage page and usage values in string form for unknown values + +void HIDGetUsageName (const long valueUsagePage, const long valueUsage, char * cstrName) +{ + if (xml_GetUsageName(valueUsagePage, valueUsage, cstrName)) + return; + + switch (valueUsagePage) + { + case kHIDPage_Undefined: + switch (valueUsage) + { + default: sprintf (cstrName, "Undefined Page, Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_GenericDesktop: + switch (valueUsage) + { + case kHIDUsage_GD_Pointer: sprintf (cstrName, "Pointer"); break; + case kHIDUsage_GD_Mouse: sprintf (cstrName, "Mouse"); break; + case kHIDUsage_GD_Joystick: sprintf (cstrName, "Joystick"); break; + case kHIDUsage_GD_GamePad: sprintf (cstrName, "GamePad"); break; + case kHIDUsage_GD_Keyboard: sprintf (cstrName, "Keyboard"); break; + case kHIDUsage_GD_Keypad: sprintf (cstrName, "Keypad"); break; + case kHIDUsage_GD_MultiAxisController: sprintf (cstrName, "Multi-Axis Controller"); break; + + case kHIDUsage_GD_X: sprintf (cstrName, "X-Axis"); break; + case kHIDUsage_GD_Y: sprintf (cstrName, "Y-Axis"); break; + case kHIDUsage_GD_Z: sprintf (cstrName, "Z-Axis"); break; + case kHIDUsage_GD_Rx: sprintf (cstrName, "X-Rotation"); break; + case kHIDUsage_GD_Ry: sprintf (cstrName, "Y-Rotation"); break; + case kHIDUsage_GD_Rz: sprintf (cstrName, "Z-Rotation"); break; + case kHIDUsage_GD_Slider: sprintf (cstrName, "Slider"); break; + case kHIDUsage_GD_Dial: sprintf (cstrName, "Dial"); break; + case kHIDUsage_GD_Wheel: sprintf (cstrName, "Wheel"); break; + case kHIDUsage_GD_Hatswitch: sprintf (cstrName, "Hatswitch"); break; + case kHIDUsage_GD_CountedBuffer: sprintf (cstrName, "Counted Buffer"); break; + case kHIDUsage_GD_ByteCount: sprintf (cstrName, "Byte Count"); break; + case kHIDUsage_GD_MotionWakeup: sprintf (cstrName, "Motion Wakeup"); break; + case kHIDUsage_GD_Start: sprintf (cstrName, "Start"); break; + case kHIDUsage_GD_Select: sprintf (cstrName, "Select"); break; + + case kHIDUsage_GD_Vx: sprintf (cstrName, "X-Velocity"); break; + case kHIDUsage_GD_Vy: sprintf (cstrName, "Y-Velocity"); break; + case kHIDUsage_GD_Vz: sprintf (cstrName, "Z-Velocity"); break; + case kHIDUsage_GD_Vbrx: sprintf (cstrName, "X-Rotation Velocity"); break; + case kHIDUsage_GD_Vbry: sprintf (cstrName, "Y-Rotation Velocity"); break; + case kHIDUsage_GD_Vbrz: sprintf (cstrName, "Z-Rotation Velocity"); break; + case kHIDUsage_GD_Vno: sprintf (cstrName, "Vno"); break; + + case kHIDUsage_GD_SystemControl: sprintf (cstrName, "System Control"); break; + case kHIDUsage_GD_SystemPowerDown: sprintf (cstrName, "System Power Down"); break; + case kHIDUsage_GD_SystemSleep: sprintf (cstrName, "System Sleep"); break; + case kHIDUsage_GD_SystemWakeUp: sprintf (cstrName, "System Wake Up"); break; + case kHIDUsage_GD_SystemContextMenu: sprintf (cstrName, "System Context Menu"); break; + case kHIDUsage_GD_SystemMainMenu: sprintf (cstrName, "System Main Menu"); break; + case kHIDUsage_GD_SystemAppMenu: sprintf (cstrName, "System App Menu"); break; + case kHIDUsage_GD_SystemMenuHelp: sprintf (cstrName, "System Menu Help"); break; + case kHIDUsage_GD_SystemMenuExit: sprintf (cstrName, "System Menu Exit"); break; + case kHIDUsage_GD_SystemMenu: sprintf (cstrName, "System Menu"); break; + case kHIDUsage_GD_SystemMenuRight: sprintf (cstrName, "System Menu Right"); break; + case kHIDUsage_GD_SystemMenuLeft: sprintf (cstrName, "System Menu Left"); break; + case kHIDUsage_GD_SystemMenuUp: sprintf (cstrName, "System Menu Up"); break; + case kHIDUsage_GD_SystemMenuDown: sprintf (cstrName, "System Menu Down"); break; + + case kHIDUsage_GD_DPadUp: sprintf (cstrName, "DPad Up"); break; + case kHIDUsage_GD_DPadDown: sprintf (cstrName, "DPad Down"); break; + case kHIDUsage_GD_DPadRight: sprintf (cstrName, "DPad Right"); break; + case kHIDUsage_GD_DPadLeft: sprintf (cstrName, "DPad Left"); break; + + case kHIDUsage_GD_Reserved: sprintf (cstrName, "Reserved"); break; + + default: sprintf (cstrName, "Generic Desktop Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_Simulation: + switch (valueUsage) + { + default: sprintf (cstrName, "Simulation Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_VR: + switch (valueUsage) + { + default: sprintf (cstrName, "VR Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_Sport: + switch (valueUsage) + { + default: sprintf (cstrName, "Sport Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_Game: + switch (valueUsage) + { + default: sprintf (cstrName, "Game Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_KeyboardOrKeypad: + switch (valueUsage) + { + default: sprintf (cstrName, "Keyboard Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_LEDs: + switch (valueUsage) + { + // some LED usages + case kHIDUsage_LED_IndicatorRed: sprintf (cstrName, "Red LED"); break; + case kHIDUsage_LED_IndicatorGreen: sprintf (cstrName, "Green LED"); break; + case kHIDUsage_LED_IndicatorAmber: sprintf (cstrName, "Amber LED"); break; + case kHIDUsage_LED_GenericIndicator: sprintf (cstrName, "Generic LED"); break; + case kHIDUsage_LED_SystemSuspend: sprintf (cstrName, "System Suspend LED"); break; + case kHIDUsage_LED_ExternalPowerConnected: sprintf (cstrName, "External Power LED"); break; + default: sprintf (cstrName, "LED Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_Button: + switch (valueUsage) + { + default: sprintf (cstrName, "Button #%ld", valueUsage); break; + } + break; + case kHIDPage_Ordinal: + switch (valueUsage) + { + default: sprintf (cstrName, "Ordinal Instance %lx", valueUsage); break; + } + break; + case kHIDPage_Telephony: + switch (valueUsage) + { + default: sprintf (cstrName, "Telephony Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_Consumer: + switch (valueUsage) + { + default: sprintf (cstrName, "Consumer Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_Digitizer: + switch (valueUsage) + { + default: sprintf (cstrName, "Digitizer Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_PID: + if (((valueUsage >= 0x02) && (valueUsage <= 0x1F)) || ((valueUsage >= 0x29) && (valueUsage <= 0x2F)) || + ((valueUsage >= 0x35) && (valueUsage <= 0x3F)) || ((valueUsage >= 0x44) && (valueUsage <= 0x4F)) || + (valueUsage == 0x8A) || (valueUsage == 0x93) || ((valueUsage >= 0x9D) && (valueUsage <= 0x9E)) || + ((valueUsage >= 0xA1) && (valueUsage <= 0xA3)) || ((valueUsage >= 0xAD) && (valueUsage <= 0xFFFF))) + sprintf (cstrName, "PID Reserved"); + else + switch (valueUsage) + { + case 0x00: sprintf (cstrName, "PID Undefined Usage"); break; + case kHIDUsage_PID_PhysicalInterfaceDevice: sprintf (cstrName, "Physical Interface Device"); break; + case kHIDUsage_PID_Normal: sprintf (cstrName, "Normal Force"); break; + + case kHIDUsage_PID_SetEffectReport: sprintf (cstrName, "Set Effect Report"); break; + case kHIDUsage_PID_EffectBlockIndex: sprintf (cstrName, "Effect Block Index"); break; + case kHIDUsage_PID_ParamBlockOffset: sprintf (cstrName, "Parameter Block Offset"); break; + case kHIDUsage_PID_ROM_Flag: sprintf (cstrName, "ROM Flag"); break; + + case kHIDUsage_PID_EffectType: sprintf (cstrName, "Effect Type"); break; + case kHIDUsage_PID_ET_ConstantForce: sprintf (cstrName, "Effect Type Constant Force"); break; + case kHIDUsage_PID_ET_Ramp: sprintf (cstrName, "Effect Type Ramp"); break; + case kHIDUsage_PID_ET_CustomForceData: sprintf (cstrName, "Effect Type Custom Force Data"); break; + case kHIDUsage_PID_ET_Square: sprintf (cstrName, "Effect Type Square"); break; + case kHIDUsage_PID_ET_Sine: sprintf (cstrName, "Effect Type Sine"); break; + case kHIDUsage_PID_ET_Triangle: sprintf (cstrName, "Effect Type Triangle"); break; + case kHIDUsage_PID_ET_SawtoothUp: sprintf (cstrName, "Effect Type Sawtooth Up"); break; + case kHIDUsage_PID_ET_SawtoothDown: sprintf (cstrName, "Effect Type Sawtooth Down"); break; + case kHIDUsage_PID_ET_Spring: sprintf (cstrName, "Effect Type Spring"); break; + case kHIDUsage_PID_ET_Damper: sprintf (cstrName, "Effect Type Damper"); break; + case kHIDUsage_PID_ET_Inertia: sprintf (cstrName, "Effect Type Inertia"); break; + case kHIDUsage_PID_ET_Friction: sprintf (cstrName, "Effect Type Friction"); break; + case kHIDUsage_PID_Duration: sprintf (cstrName, "Effect Duration"); break; + case kHIDUsage_PID_SamplePeriod: sprintf (cstrName, "Effect Sample Period"); break; + case kHIDUsage_PID_Gain: sprintf (cstrName, "Effect Gain"); break; + case kHIDUsage_PID_TriggerButton: sprintf (cstrName, "Effect Trigger Button"); break; + case kHIDUsage_PID_TriggerRepeatInterval: sprintf (cstrName, "Effect Trigger Repeat Interval"); break; + + case kHIDUsage_PID_AxesEnable: sprintf (cstrName, "Axis Enable"); break; + case kHIDUsage_PID_DirectionEnable: sprintf (cstrName, "Direction Enable"); break; + + case kHIDUsage_PID_Direction: sprintf (cstrName, "Direction"); break; + + case kHIDUsage_PID_TypeSpecificBlockOffset: sprintf (cstrName, "Type Specific Block Offset"); break; + + case kHIDUsage_PID_BlockType: sprintf (cstrName, "Block Type"); break; + + case kHIDUsage_PID_SetEnvelopeReport: sprintf (cstrName, "Set Envelope Report"); break; + case kHIDUsage_PID_AttackLevel: sprintf (cstrName, "Envelope Attack Level"); break; + case kHIDUsage_PID_AttackTime: sprintf (cstrName, "Envelope Attack Time"); break; + case kHIDUsage_PID_FadeLevel: sprintf (cstrName, "Envelope Fade Level"); break; + case kHIDUsage_PID_FadeTime: sprintf (cstrName, "Envelope Fade Time"); break; + + case kHIDUsage_PID_SetConditionReport: sprintf (cstrName, "Set Condition Report"); break; + case kHIDUsage_PID_CP_Offset: sprintf (cstrName, "Condition CP Offset"); break; + case kHIDUsage_PID_PositiveCoefficient: sprintf (cstrName, "Condition Positive Coefficient"); break; + case kHIDUsage_PID_NegativeCoefficient: sprintf (cstrName, "Condition Negative Coefficient"); break; + case kHIDUsage_PID_PositiveSaturation: sprintf (cstrName, "Condition Positive Saturation"); break; + case kHIDUsage_PID_NegativeSaturation: sprintf (cstrName, "Condition Negative Saturation"); break; + case kHIDUsage_PID_DeadBand: sprintf (cstrName, "Condition Dead Band"); break; + + case kHIDUsage_PID_DownloadForceSample: sprintf (cstrName, "Download Force Sample"); break; + case kHIDUsage_PID_IsochCustomForceEnable: sprintf (cstrName, "Isoch Custom Force Enable"); break; + + case kHIDUsage_PID_CustomForceDataReport: sprintf (cstrName, "Custom Force Data Report"); break; + case kHIDUsage_PID_CustomForceData: sprintf (cstrName, "Custom Force Data"); break; + + case kHIDUsage_PID_CustomForceVendorDefinedData: sprintf (cstrName, "Custom Force Vendor Defined Data"); break; + case kHIDUsage_PID_SetCustomForceReport: sprintf (cstrName, "Set Custom Force Report"); break; + case kHIDUsage_PID_CustomForceDataOffset: sprintf (cstrName, "Custom Force Data Offset"); break; + case kHIDUsage_PID_SampleCount: sprintf (cstrName, "Custom Force Sample Count"); break; + + case kHIDUsage_PID_SetPeriodicReport: sprintf (cstrName, "Set Periodic Report"); break; + case kHIDUsage_PID_Offset: sprintf (cstrName, "Periodic Offset"); break; + case kHIDUsage_PID_Magnitude: sprintf (cstrName, "Periodic Magnitude"); break; + case kHIDUsage_PID_Phase: sprintf (cstrName, "Periodic Phase"); break; + case kHIDUsage_PID_Period: sprintf (cstrName, "Periodic Period"); break; + + case kHIDUsage_PID_SetConstantForceReport: sprintf (cstrName, "Set Constant Force Report"); break; + + case kHIDUsage_PID_SetRampForceReport: sprintf (cstrName, "Set Ramp Force Report"); break; + case kHIDUsage_PID_RampStart: sprintf (cstrName, "Ramp Start"); break; + case kHIDUsage_PID_RampEnd: sprintf (cstrName, "Ramp End"); break; + + case kHIDUsage_PID_EffectOperationReport: sprintf (cstrName, "Effect Operation Report"); break; + + case kHIDUsage_PID_EffectOperation: sprintf (cstrName, "Effect Operation"); break; + case kHIDUsage_PID_OpEffectStart: sprintf (cstrName, "Op Effect Start"); break; + case kHIDUsage_PID_OpEffectStartSolo: sprintf (cstrName, "Op Effect Start Solo"); break; + case kHIDUsage_PID_OpEffectStop: sprintf (cstrName, "Op Effect Stop"); break; + case kHIDUsage_PID_LoopCount: sprintf (cstrName, "Op Effect Loop Count"); break; + + case kHIDUsage_PID_DeviceGainReport: sprintf (cstrName, "Device Gain Report"); break; + case kHIDUsage_PID_DeviceGain: sprintf (cstrName, "Device Gain"); break; + + case kHIDUsage_PID_PoolReport: sprintf (cstrName, "PID Pool Report"); break; + case kHIDUsage_PID_RAM_PoolSize: sprintf (cstrName, "RAM Pool Size"); break; + case kHIDUsage_PID_ROM_PoolSize: sprintf (cstrName, "ROM Pool Size"); break; + case kHIDUsage_PID_ROM_EffectBlockCount: sprintf (cstrName, "ROM Effect Block Count"); break; + case kHIDUsage_PID_SimultaneousEffectsMax: sprintf (cstrName, "Simultaneous Effects Max"); break; + case kHIDUsage_PID_PoolAlignment: sprintf (cstrName, "Pool Alignment"); break; + + case kHIDUsage_PID_PoolMoveReport: sprintf (cstrName, "PID Pool Move Report"); break; + case kHIDUsage_PID_MoveSource: sprintf (cstrName, "Move Source"); break; + case kHIDUsage_PID_MoveDestination: sprintf (cstrName, "Move Destination"); break; + case kHIDUsage_PID_MoveLength: sprintf (cstrName, "Move Length"); break; + + case kHIDUsage_PID_BlockLoadReport: sprintf (cstrName, "PID Block Load Report"); break; + + case kHIDUsage_PID_BlockLoadStatus: sprintf (cstrName, "Block Load Status"); break; + case kHIDUsage_PID_BlockLoadSuccess: sprintf (cstrName, "Block Load Success"); break; + case kHIDUsage_PID_BlockLoadFull: sprintf (cstrName, "Block Load Full"); break; + case kHIDUsage_PID_BlockLoadError: sprintf (cstrName, "Block Load Error"); break; + case kHIDUsage_PID_BlockHandle: sprintf (cstrName, "Block Handle"); break; + + case kHIDUsage_PID_BlockFreeReport: sprintf (cstrName, "PID Block Free Report"); break; + + case kHIDUsage_PID_TypeSpecificBlockHandle: sprintf (cstrName, "Type Specific Block Handle"); break; + + case kHIDUsage_PID_StateReport: sprintf (cstrName, "PID State Report"); break; + case kHIDUsage_PID_EffectPlaying: sprintf (cstrName, "Effect Playing"); break; + + case kHIDUsage_PID_DeviceControlReport: sprintf (cstrName, "PID Device Control Report"); break; + + case kHIDUsage_PID_DeviceControl: sprintf (cstrName, "PID Device Control"); break; + case kHIDUsage_PID_DC_EnableActuators: sprintf (cstrName, "Device Control Enable Actuators"); break; + case kHIDUsage_PID_DC_DisableActuators: sprintf (cstrName, "Device Control Disable Actuators"); break; + case kHIDUsage_PID_DC_StopAllEffects: sprintf (cstrName, "Device Control Stop All Effects"); break; + case kHIDUsage_PID_DC_DeviceReset: sprintf (cstrName, "Device Control Reset"); break; + case kHIDUsage_PID_DC_DevicePause: sprintf (cstrName, "Device Control Pause"); break; + case kHIDUsage_PID_DC_DeviceContinue: sprintf (cstrName, "Device Control Continue"); break; + case kHIDUsage_PID_DevicePaused: sprintf (cstrName, "Device Paused"); break; + case kHIDUsage_PID_ActuatorsEnabled: sprintf (cstrName, "Actuators Enabled"); break; + case kHIDUsage_PID_SafetySwitch: sprintf (cstrName, "Safety Switch"); break; + case kHIDUsage_PID_ActuatorOverrideSwitch: sprintf (cstrName, "Actuator Override Switch"); break; + case kHIDUsage_PID_ActuatorPower: sprintf (cstrName, "Actuator Power"); break; + case kHIDUsage_PID_StartDelay: sprintf (cstrName, "Start Delay"); break; + + case kHIDUsage_PID_ParameterBlockSize: sprintf (cstrName, "Parameter Block Size"); break; + case kHIDUsage_PID_DeviceManagedPool: sprintf (cstrName, "Device Managed Pool"); break; + case kHIDUsage_PID_SharedParameterBlocks: sprintf (cstrName, "Shared Parameter Blocks"); break; + + case kHIDUsage_PID_CreateNewEffectReport: sprintf (cstrName, "Create New Effect Report"); break; + case kHIDUsage_PID_RAM_PoolAvailable: sprintf (cstrName, "RAM Pool Available"); break; + default: sprintf (cstrName, "PID Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_Unicode: + switch (valueUsage) + { + default: sprintf (cstrName, "Unicode Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_PowerDevice: + if (((valueUsage >= 0x06) && (valueUsage <= 0x0F)) || ((valueUsage >= 0x26) && (valueUsage <= 0x2F)) || + ((valueUsage >= 0x39) && (valueUsage <= 0x3F)) || ((valueUsage >= 0x48) && (valueUsage <= 0x4F)) || + ((valueUsage >= 0x58) && (valueUsage <= 0x5F)) || (valueUsage == 0x6A) || + ((valueUsage >= 0x74) && (valueUsage <= 0xFC))) + sprintf (cstrName, "Power Device Reserved"); + else + switch (valueUsage) + { + case kHIDUsage_PD_Undefined: sprintf (cstrName, "Power Device Undefined Usage"); break; + case kHIDUsage_PD_iName: sprintf (cstrName, "Power Device Name Index"); break; + case kHIDUsage_PD_PresentStatus: sprintf (cstrName, "Power Device Present Status"); break; + case kHIDUsage_PD_ChangedStatus: sprintf (cstrName, "Power Device Changed Status"); break; + case kHIDUsage_PD_UPS: sprintf (cstrName, "Uninterruptible Power Supply"); break; + case kHIDUsage_PD_PowerSupply: sprintf (cstrName, "Power Supply"); break; + + case kHIDUsage_PD_BatterySystem: sprintf (cstrName, "Battery System Power Module"); break; + case kHIDUsage_PD_BatterySystemID: sprintf (cstrName, "Battery System ID"); break; + case kHIDUsage_PD_Battery: sprintf (cstrName, "Battery"); break; + case kHIDUsage_PD_BatteryID: sprintf (cstrName, "Battery ID"); break; + case kHIDUsage_PD_Charger: sprintf (cstrName, "Charger"); break; + case kHIDUsage_PD_ChargerID: sprintf (cstrName, "Charger ID"); break; + case kHIDUsage_PD_PowerConverter: sprintf (cstrName, "Power Converter Power Module"); break; + case kHIDUsage_PD_PowerConverterID: sprintf (cstrName, "Power Converter ID"); break; + case kHIDUsage_PD_OutletSystem: sprintf (cstrName, "Outlet System power module"); break; + case kHIDUsage_PD_OutletSystemID: sprintf (cstrName, "Outlet System ID"); break; + case kHIDUsage_PD_Input: sprintf (cstrName, "Power Device Input"); break; + case kHIDUsage_PD_InputID: sprintf (cstrName, "Power Device Input ID"); break; + case kHIDUsage_PD_Output: sprintf (cstrName, "Power Device Output"); break; + case kHIDUsage_PD_OutputID: sprintf (cstrName, "Power Device Output ID"); break; + case kHIDUsage_PD_Flow: sprintf (cstrName, "Power Device Flow"); break; + case kHIDUsage_PD_FlowID: sprintf (cstrName, "Power Device Flow ID"); break; + case kHIDUsage_PD_Outlet: sprintf (cstrName, "Power Device Outlet"); break; + case kHIDUsage_PD_OutletID: sprintf (cstrName, "Power Device Outlet ID"); break; + case kHIDUsage_PD_Gang: sprintf (cstrName, "Power Device Gang"); break; + case kHIDUsage_PD_GangID: sprintf (cstrName, "Power Device Gang ID"); break; + case kHIDUsage_PD_PowerSummary: sprintf (cstrName, "Power Device Power Summary"); break; + case kHIDUsage_PD_PowerSummaryID: sprintf (cstrName, "Power Device Power Summary ID"); break; + + case kHIDUsage_PD_Voltage: sprintf (cstrName, "Power Device Voltage"); break; + case kHIDUsage_PD_Current: sprintf (cstrName, "Power Device Current"); break; + case kHIDUsage_PD_Frequency: sprintf (cstrName, "Power Device Frequency"); break; + case kHIDUsage_PD_ApparentPower: sprintf (cstrName, "Power Device Apparent Power"); break; + case kHIDUsage_PD_ActivePower: sprintf (cstrName, "Power Device RMS Power"); break; + case kHIDUsage_PD_PercentLoad: sprintf (cstrName, "Power Device Percent Load"); break; + case kHIDUsage_PD_Temperature: sprintf (cstrName, "Power Device Temperature"); break; + case kHIDUsage_PD_Humidity: sprintf (cstrName, "Power Device Humidity"); break; + case kHIDUsage_PD_BadCount: sprintf (cstrName, "Power Device Bad Condition Count"); break; + + case kHIDUsage_PD_ConfigVoltage: sprintf (cstrName, "Power Device Nominal Voltage"); break; + case kHIDUsage_PD_ConfigCurrent: sprintf (cstrName, "Power Device Nominal Current"); break; + case kHIDUsage_PD_ConfigFrequency: sprintf (cstrName, "Power Device Nominal Frequency"); break; + case kHIDUsage_PD_ConfigApparentPower: sprintf (cstrName, "Power Device Nominal Apparent Power"); break; + case kHIDUsage_PD_ConfigActivePower: sprintf (cstrName, "Power Device Nominal RMS Power"); break; + case kHIDUsage_PD_ConfigPercentLoad: sprintf (cstrName, "Power Device Nominal Percent Load"); break; + case kHIDUsage_PD_ConfigTemperature: sprintf (cstrName, "Power Device Nominal Temperature"); break; + + case kHIDUsage_PD_ConfigHumidity: sprintf (cstrName, "Power Device Nominal Humidity"); break; + case kHIDUsage_PD_SwitchOnControl: sprintf (cstrName, "Power Device Switch On Control"); break; + case kHIDUsage_PD_SwitchOffControl: sprintf (cstrName, "Power Device Switch Off Control"); break; + case kHIDUsage_PD_ToggleControl: sprintf (cstrName, "Power Device Toogle Sequence Control"); break; + case kHIDUsage_PD_LowVoltageTransfer: sprintf (cstrName, "Power Device Min Transfer Voltage"); break; + case kHIDUsage_PD_HighVoltageTransfer: sprintf (cstrName, "Power Device Max Transfer Voltage"); break; + case kHIDUsage_PD_DelayBeforeReboot: sprintf (cstrName, "Power Device Delay Before Reboot"); break; + case kHIDUsage_PD_DelayBeforeStartup: sprintf (cstrName, "Power Device Delay Before Startup"); break; + case kHIDUsage_PD_DelayBeforeShutdown: sprintf (cstrName, "Power Device Delay Before Shutdown"); break; + case kHIDUsage_PD_Test: sprintf (cstrName, "Power Device Test Request/Result"); break; + case kHIDUsage_PD_ModuleReset: sprintf (cstrName, "Power Device Reset Request/Result"); break; + case kHIDUsage_PD_AudibleAlarmControl: sprintf (cstrName, "Power Device Audible Alarm Control"); break; + + case kHIDUsage_PD_Present: sprintf (cstrName, "Power Device Present"); break; + case kHIDUsage_PD_Good: sprintf (cstrName, "Power Device Good"); break; + case kHIDUsage_PD_InternalFailure: sprintf (cstrName, "Power Device Internal Failure"); break; + case kHIDUsage_PD_VoltageOutOfRange: sprintf (cstrName, "Power Device Voltage Out Of Range"); break; + case kHIDUsage_PD_FrequencyOutOfRange: sprintf (cstrName, "Power Device Frequency Out Of Range"); break; + case kHIDUsage_PD_Overload: sprintf (cstrName, "Power Device Overload"); break; + case kHIDUsage_PD_OverCharged: sprintf (cstrName, "Power Device Over Charged"); break; + case kHIDUsage_PD_OverTemperature: sprintf (cstrName, "Power Device Over Temperature"); break; + case kHIDUsage_PD_ShutdownRequested: sprintf (cstrName, "Power Device Shutdown Requested"); break; + + case kHIDUsage_PD_ShutdownImminent: sprintf (cstrName, "Power Device Shutdown Imminent"); break; + case kHIDUsage_PD_SwitchOnOff: sprintf (cstrName, "Power Device On/Off Switch Status"); break; + case kHIDUsage_PD_Switchable: sprintf (cstrName, "Power Device Switchable"); break; + case kHIDUsage_PD_Used: sprintf (cstrName, "Power Device Used"); break; + case kHIDUsage_PD_Boost: sprintf (cstrName, "Power Device Boosted"); break; + case kHIDUsage_PD_Buck: sprintf (cstrName, "Power Device Bucked"); break; + case kHIDUsage_PD_Initialized: sprintf (cstrName, "Power Device Initialized"); break; + case kHIDUsage_PD_Tested: sprintf (cstrName, "Power Device Tested"); break; + case kHIDUsage_PD_AwaitingPower: sprintf (cstrName, "Power Device Awaiting Power"); break; + case kHIDUsage_PD_CommunicationLost: sprintf (cstrName, "Power Device Communication Lost"); break; + + case kHIDUsage_PD_iManufacturer: sprintf (cstrName, "Power Device Manufacturer String Index"); break; + case kHIDUsage_PD_iProduct: sprintf (cstrName, "Power Device Product String Index"); break; + case kHIDUsage_PD_iserialNumber: sprintf (cstrName, "Power Device Serial Number String Index"); break; + default: sprintf (cstrName, "Power Device Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_BatterySystem: + if (((valueUsage >= 0x0A) && (valueUsage <= 0x0F)) || ((valueUsage >= 0x1E) && (valueUsage <= 0x27)) || + ((valueUsage >= 0x30) && (valueUsage <= 0x3F)) || ((valueUsage >= 0x4C) && (valueUsage <= 0x5F)) || + ((valueUsage >= 0x6C) && (valueUsage <= 0x7F)) || ((valueUsage >= 0x90) && (valueUsage <= 0xBF)) || + ((valueUsage >= 0xC3) && (valueUsage <= 0xCF)) || ((valueUsage >= 0xDD) && (valueUsage <= 0xEF)) || + ((valueUsage >= 0xF2) && (valueUsage <= 0xFF))) + sprintf (cstrName, "Power Device Reserved"); + else + switch (valueUsage) + { + case kHIDUsage_BS_Undefined: sprintf (cstrName, "Battery System Undefined"); break; + case kHIDUsage_BS_SMBBatteryMode: sprintf (cstrName, "SMB Mode"); break; + case kHIDUsage_BS_SMBBatteryStatus: sprintf (cstrName, "SMB Status"); break; + case kHIDUsage_BS_SMBAlarmWarning: sprintf (cstrName, "SMB Alarm Warning"); break; + case kHIDUsage_BS_SMBChargerMode: sprintf (cstrName, "SMB Charger Mode"); break; + case kHIDUsage_BS_SMBChargerStatus: sprintf (cstrName, "SMB Charger Status"); break; + case kHIDUsage_BS_SMBChargerSpecInfo: sprintf (cstrName, "SMB Charger Extended Status"); break; + case kHIDUsage_BS_SMBSelectorState: sprintf (cstrName, "SMB Selector State"); break; + case kHIDUsage_BS_SMBSelectorPresets: sprintf (cstrName, "SMB Selector Presets"); break; + case kHIDUsage_BS_SMBSelectorInfo: sprintf (cstrName, "SMB Selector Info"); break; + case kHIDUsage_BS_OptionalMfgFunction1: sprintf (cstrName, "Battery System Optional SMB Mfg Function 1"); break; + case kHIDUsage_BS_OptionalMfgFunction2: sprintf (cstrName, "Battery System Optional SMB Mfg Function 2"); break; + case kHIDUsage_BS_OptionalMfgFunction3: sprintf (cstrName, "Battery System Optional SMB Mfg Function 3"); break; + case kHIDUsage_BS_OptionalMfgFunction4: sprintf (cstrName, "Battery System Optional SMB Mfg Function 4"); break; + case kHIDUsage_BS_OptionalMfgFunction5: sprintf (cstrName, "Battery System Optional SMB Mfg Function 5"); break; + case kHIDUsage_BS_ConnectionToSMBus: sprintf (cstrName, "Battery System Connection To System Management Bus"); break; + case kHIDUsage_BS_OutputConnection: sprintf (cstrName, "Battery System Output Connection Status"); break; + case kHIDUsage_BS_ChargerConnection: sprintf (cstrName, "Battery System Charger Connection"); break; + case kHIDUsage_BS_BatteryInsertion: sprintf (cstrName, "Battery System Battery Insertion"); break; + case kHIDUsage_BS_Usenext: sprintf (cstrName, "Battery System Use Next"); break; + case kHIDUsage_BS_OKToUse: sprintf (cstrName, "Battery System OK To Use"); break; + case kHIDUsage_BS_BatterySupported: sprintf (cstrName, "Battery System Battery Supported"); break; + case kHIDUsage_BS_SelectorRevision: sprintf (cstrName, "Battery System Selector Revision"); break; + case kHIDUsage_BS_ChargingIndicator: sprintf (cstrName, "Battery System Charging Indicator"); break; + case kHIDUsage_BS_ManufacturerAccess: sprintf (cstrName, "Battery System Manufacturer Access"); break; + case kHIDUsage_BS_RemainingCapacityLimit: sprintf (cstrName, "Battery System Remaining Capacity Limit"); break; + case kHIDUsage_BS_RemainingTimeLimit: sprintf (cstrName, "Battery System Remaining Time Limit"); break; + case kHIDUsage_BS_AtRate: sprintf (cstrName, "Battery System At Rate..."); break; + case kHIDUsage_BS_CapacityMode: sprintf (cstrName, "Battery System Capacity Mode"); break; + case kHIDUsage_BS_BroadcastToCharger: sprintf (cstrName, "Battery System Broadcast To Charger"); break; + case kHIDUsage_BS_PrimaryBattery: sprintf (cstrName, "Battery System Primary Battery"); break; + case kHIDUsage_BS_ChargeController: sprintf (cstrName, "Battery System Charge Controller"); break; + case kHIDUsage_BS_TerminateCharge: sprintf (cstrName, "Battery System Terminate Charge"); break; + case kHIDUsage_BS_TerminateDischarge: sprintf (cstrName, "Battery System Terminate Discharge"); break; + case kHIDUsage_BS_BelowRemainingCapacityLimit: sprintf (cstrName, "Battery System Below Remaining Capacity Limit"); break; + case kHIDUsage_BS_RemainingTimeLimitExpired: sprintf (cstrName, "Battery System Remaining Time Limit Expired"); break; + case kHIDUsage_BS_Charging: sprintf (cstrName, "Battery System Charging"); break; + case kHIDUsage_BS_Discharging: sprintf (cstrName, "Battery System Discharging"); break; + case kHIDUsage_BS_FullyCharged: sprintf (cstrName, "Battery System Fully Charged"); break; + case kHIDUsage_BS_FullyDischarged: sprintf (cstrName, "Battery System Fully Discharged"); break; + case kHIDUsage_BS_ConditioningFlag: sprintf (cstrName, "Battery System Conditioning Flag"); break; + case kHIDUsage_BS_AtRateOK: sprintf (cstrName, "Battery System At Rate OK"); break; + case kHIDUsage_BS_SMBErrorCode: sprintf (cstrName, "Battery System SMB Error Code"); break; + case kHIDUsage_BS_NeedReplacement: sprintf (cstrName, "Battery System Need Replacement"); break; + case kHIDUsage_BS_AtRateTimeToFull: sprintf (cstrName, "Battery System At Rate Time To Full"); break; + case kHIDUsage_BS_AtRateTimeToEmpty: sprintf (cstrName, "Battery System At Rate Time To Empty"); break; + case kHIDUsage_BS_AverageCurrent: sprintf (cstrName, "Battery System Average Current"); break; + case kHIDUsage_BS_Maxerror: sprintf (cstrName, "Battery System Max Error"); break; + case kHIDUsage_BS_RelativeStateOfCharge: sprintf (cstrName, "Battery System Relative State Of Charge"); break; + case kHIDUsage_BS_AbsoluteStateOfCharge: sprintf (cstrName, "Battery System Absolute State Of Charge"); break; + case kHIDUsage_BS_RemainingCapacity: sprintf (cstrName, "Battery System Remaining Capacity"); break; + case kHIDUsage_BS_FullChargeCapacity: sprintf (cstrName, "Battery System Full Charge Capacity"); break; + case kHIDUsage_BS_RunTimeToEmpty: sprintf (cstrName, "Battery System Run Time To Empty"); break; + case kHIDUsage_BS_AverageTimeToEmpty: sprintf (cstrName, "Battery System Average Time To Empty"); break; + case kHIDUsage_BS_AverageTimeToFull: sprintf (cstrName, "Battery System Average Time To Full"); break; + case kHIDUsage_BS_CycleCount: sprintf (cstrName, "Battery System Cycle Count"); break; + case kHIDUsage_BS_BattPackModelLevel: sprintf (cstrName, "Battery System Batt Pack Model Level"); break; + case kHIDUsage_BS_InternalChargeController: sprintf (cstrName, "Battery System Internal Charge Controller"); break; + case kHIDUsage_BS_PrimaryBatterySupport: sprintf (cstrName, "Battery System Primary Battery Support"); break; + case kHIDUsage_BS_DesignCapacity: sprintf (cstrName, "Battery System Design Capacity"); break; + case kHIDUsage_BS_SpecificationInfo: sprintf (cstrName, "Battery System Specification Info"); break; + case kHIDUsage_BS_ManufacturerDate: sprintf (cstrName, "Battery System Manufacturer Date"); break; + case kHIDUsage_BS_SerialNumber: sprintf (cstrName, "Battery System Serial Number"); break; + case kHIDUsage_BS_iManufacturerName: sprintf (cstrName, "Battery System Manufacturer Name Index"); break; + case kHIDUsage_BS_iDevicename: sprintf (cstrName, "Battery System Device Name Index"); break; + case kHIDUsage_BS_iDeviceChemistry: sprintf (cstrName, "Battery System Device Chemistry Index"); break; + case kHIDUsage_BS_ManufacturerData: sprintf (cstrName, "Battery System Manufacturer Data"); break; + case kHIDUsage_BS_Rechargable: sprintf (cstrName, "Battery System Rechargable"); break; + case kHIDUsage_BS_WarningCapacityLimit: sprintf (cstrName, "Battery System Warning Capacity Limit"); break; + case kHIDUsage_BS_CapacityGranularity1: sprintf (cstrName, "Battery System Capacity Granularity 1"); break; + case kHIDUsage_BS_CapacityGranularity2: sprintf (cstrName, "Battery System Capacity Granularity 2"); break; + case kHIDUsage_BS_iOEMInformation: sprintf (cstrName, "Battery System OEM Information Index"); break; + case kHIDUsage_BS_InhibitCharge: sprintf (cstrName, "Battery System Inhibit Charge"); break; + case kHIDUsage_BS_EnablePolling: sprintf (cstrName, "Battery System Enable Polling"); break; + case kHIDUsage_BS_ResetToZero: sprintf (cstrName, "Battery System Reset To Zero"); break; + case kHIDUsage_BS_ACPresent: sprintf (cstrName, "Battery System AC Present"); break; + case kHIDUsage_BS_BatteryPresent: sprintf (cstrName, "Battery System Battery Present"); break; + case kHIDUsage_BS_PowerFail: sprintf (cstrName, "Battery System Power Fail"); break; + case kHIDUsage_BS_AlarmInhibited: sprintf (cstrName, "Battery System Alarm Inhibited"); break; + case kHIDUsage_BS_ThermistorUnderRange: sprintf (cstrName, "Battery System Thermistor Under Range"); break; + case kHIDUsage_BS_ThermistorHot: sprintf (cstrName, "Battery System Thermistor Hot"); break; + case kHIDUsage_BS_ThermistorCold: sprintf (cstrName, "Battery System Thermistor Cold"); break; + case kHIDUsage_BS_ThermistorOverRange: sprintf (cstrName, "Battery System Thermistor Over Range"); break; + case kHIDUsage_BS_VoltageOutOfRange: sprintf (cstrName, "Battery System Voltage Out Of Range"); break; + case kHIDUsage_BS_CurrentOutOfRange: sprintf (cstrName, "Battery System Current Out Of Range"); break; + case kHIDUsage_BS_CurrentNotRegulated: sprintf (cstrName, "Battery System Current Not Regulated"); break; + case kHIDUsage_BS_VoltageNotRegulated: sprintf (cstrName, "Battery System Voltage Not Regulated"); break; + case kHIDUsage_BS_MasterMode: sprintf (cstrName, "Battery System Master Mode"); break; + case kHIDUsage_BS_ChargerSelectorSupport: sprintf (cstrName, "Battery System Charger Support Selector"); break; + case kHIDUsage_BS_ChargerSpec: sprintf (cstrName, "attery System Charger Specification"); break; + case kHIDUsage_BS_Level2: sprintf (cstrName, "Battery System Charger Level 2"); break; + case kHIDUsage_BS_Level3: sprintf (cstrName, "Battery System Charger Level 3"); break; + default: sprintf (cstrName, "Battery System Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_AlphanumericDisplay: + switch (valueUsage) + { + default: sprintf (cstrName, "Alphanumeric Display Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_BarCodeScanner: + switch (valueUsage) + { + default: sprintf (cstrName, "Bar Code Scanner Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_Scale: + switch (valueUsage) + { + default: sprintf (cstrName, "Scale Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_CameraControl: + switch (valueUsage) + { + default: sprintf (cstrName, "Camera Control Usage 0x%lx", valueUsage); break; + } + break; + case kHIDPage_Arcade: + switch (valueUsage) + { + default: sprintf (cstrName, "Arcade Usage 0x%lx", valueUsage); break; + } + break; + default: + if (valueUsagePage > kHIDPage_VendorDefinedStart) + sprintf (cstrName, "Vendor Defined Usage 0x%lx", valueUsage); + else + sprintf (cstrName, "Page: 0x%lx, Usage: 0x%lx", valueUsagePage, valueUsage); + break; + } +} + +// --------------------------------- +// returns calibrated value given raw value passed in +// calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values + +SInt32 HIDCalibrateValue (SInt32 value, pRecElement pElement) +{ + if (NULL != pElement) + { + float deviceScale = pElement->max - pElement->min; + float readScale = pElement->calMax - pElement->calMin; + if (readScale == 0) + return value; // no scaling as + else + return ((value - pElement->calMin) * deviceScale / readScale) + pElement->min; + } + else + return 0; // bad element passed in +} + +// --------------------------------- +// returns scaled value given raw value passed in +// scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values + +SInt32 HIDScaleValue (SInt32 value, pRecElement pElement) +{ + float deviceScale = pElement->userMax - pElement->userMin; + float readScale = pElement->max - pElement->min; + if (readScale == 0) + return value; + else + return (value - pElement->min) * deviceScale / readScale + pElement->userMin; +} + +// --------------------------------- +// convert an element type to a mask +HIDElementTypeMask HIDConvertElementTypeToMask (const long type) +{ + HIDElementTypeMask result = kHIDElementTypeAll; + + switch (type) + { + case kIOHIDElementTypeInput_Misc: + case kIOHIDElementTypeInput_Button: + case kIOHIDElementTypeInput_Axis: + case kIOHIDElementTypeInput_ScanCodes: + result = kHIDElementTypeInput; + break; + case kIOHIDElementTypeOutput: + result = kHIDElementTypeOutput; + break; + case kIOHIDElementTypeFeature: + result = kHIDElementTypeFeature; + break; + case kIOHIDElementTypeCollection: + result = kHIDElementTypeCollection; + break; + default: + result = kHIDElementTypeAll; + break; + } + return result; +} + +Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice) +{ + pRecDevice pDevice, pBestDevice = NULL; + long bestScore = 0; + + // iterate over all devices + pDevice = HIDGetFirstDevice(); + while (pDevice) + { + long deviceScore = 1; + + if (pSearchDevice->vendorID && (pSearchDevice->vendorID == pDevice->vendorID)) + { + deviceScore += 10; + if (pSearchDevice->productID && (pSearchDevice->productID == pDevice->productID)) + deviceScore += 8; + } + + if ((pSearchDevice->usagePage && (pSearchDevice->usagePage == pDevice->usagePage)) && + (pSearchDevice->usage && (pSearchDevice->usage == pDevice->usage))) + deviceScore += 9; + + if (pSearchDevice->locID && (pSearchDevice->locID == pDevice->locID)) + deviceScore += 5; + + if (deviceScore > bestScore) + { + pBestDevice = pDevice; + bestScore = deviceScore; +#if 0 // set true to output scoring informaton + printf("\n-HIDFindDevice(%ld:%ld)-I-Debug, better score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score); + HIDPrintElement(pBestElement); +#endif + } + pDevice = HIDGetNextDevice(pDevice); + } + + if (NULL != pBestDevice) + { + *ppFoundDevice = pBestDevice; +#if 0 // set true to output scoring informaton + printf("\n-HIDFindDevice(%ld:%ld)-I-Debug, best score: %ld.",pSearchElement->usagePage, pSearchElement->usage, bestScore); + HIDPrintElement(pBestElement); + printf("\n"); +#endif + return true; + } + else + return false; +} + +// --------------------------------- +// find the device and element for this action +// Device: serial, vendorID, productID, location, usagePage, usage +// Element: cookie, usagePage, usage, + +Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement, + pRecDevice *ppFoundDevice, pRecElement *ppFoundElement) +{ + pRecDevice pDevice, pBestDevice = NULL; + pRecElement pElement, pBestElement = NULL; + HIDElementTypeMask hidMask = HIDConvertElementTypeToMask (pSearchElement->type); + long bestScore = 0; + + // iterate over all devices + pDevice = HIDGetFirstDevice(); + while (pDevice) + { + long deviceScore = 1; + + if (pSearchDevice->vendorID && (pSearchDevice->vendorID == pDevice->vendorID)) + { + deviceScore += 10; + if (pSearchDevice->productID && (pSearchDevice->productID == pDevice->productID)) + deviceScore += 8; + } + if ((pSearchDevice->usagePage && (pSearchDevice->usagePage == pDevice->usagePage)) && + (pSearchDevice->usage && (pSearchDevice->usage == pDevice->usage))) + deviceScore += 9; + + if (pSearchDevice->locID && (pSearchDevice->locID == pDevice->locID)) + deviceScore += 5; + + // iterate over all elements of this device + pElement = HIDGetFirstDeviceElement(pDevice, hidMask); + while (pElement) + { + long score = deviceScore; + + if ((pSearchElement->usagePage && (pSearchElement->usagePage == pElement->usagePage)) && + (pSearchElement->usage && (pSearchElement->usage == pElement->usage))) + { + score += 5; + + if (pSearchElement->cookie && (pSearchElement->cookie == pElement->cookie)) + score += 4; + } + else + score = 0; +#if 0 // set true to output scoring informaton + if (kHIDPage_KeyboardOrKeypad != pElement->usagePage) // skip keyboards here + { + printf("\n-HIDFindActionDeviceAndElement(%ld:%ld)-I-Debug, score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score); + HIDPrintElement(pElement); + } +#endif + if (score > bestScore) + { + pBestDevice = pDevice; + pBestElement = pElement; + bestScore = score; +#if 0 // set true to output scoring informaton + printf("\n-HIDFindActionDeviceAndElement(%ld:%ld)-I-Debug, better score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score); + HIDPrintElement(pBestElement); +#endif + } + pElement = HIDGetNextDeviceElement(pElement, hidMask); + } + pDevice = HIDGetNextDevice(pDevice); + } + + if ((NULL != pBestDevice) || (NULL != pBestElement)) + { + *ppFoundDevice = pBestDevice; + *ppFoundElement = pBestElement; +#if 0 // set true to output scoring informaton + printf("\n-HIDFindActionDeviceAndElement(%ld:%ld)-I-Debug, best score: %ld.",pSearchElement->usagePage, pSearchElement->usage, bestScore); + HIDPrintElement(pBestElement); + printf("\n"); +#endif + return true; + } + else + return false; +} + +// --------------------------------- +// find the device and element for this action +// Device: serial, vendorID, productID, location, usagePage, usage +// Element: cookie, usagePage, usage, + +Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement) +{ + pRecElement pElement, pBestElement = NULL; + HIDElementTypeMask hidMask = HIDConvertElementTypeToMask (pSearchElement->type); + long bestScore = 0; + + if ((NULL == pStartElement) || (NULL == pSearchElement) || (NULL == ppFoundElement)) + return false; + + // iterate over all children of this element + pElement = pStartElement->pChild; + + while (pElement) + { + long score = 0; +#if 0 // set true to output searching informaton + printf("\n-HIDFindSubElement, search = {t:%.2lX, u:%.4lX:%.4lX}, match = {t:%.2lX, u:%.4lX:%.4lX, s:\"%s\"}", + pSearchElement->type, pSearchElement->usagePage, pSearchElement->usage, + pElement->type, pElement->usagePage, pElement->usage, pElement->name); + fflush(stdout); +#endif + if ((pSearchElement->usagePage && (pSearchElement->usagePage == pElement->usagePage)) && (pSearchElement->usage && (pSearchElement->usage == pElement->usage))) + { + score += 4; + if (pSearchElement->cookie && (pSearchElement->cookie == pElement->cookie)) + score += 5; + } +#if 0 // set true to output searching informaton + if (kHIDPage_KeyboardOrKeypad != pElement->usagePage) // skip keyboards here + { + printf("\n-HIDFindSubElement(%ld:%ld)-I-Debug, score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score); + HIDPrintElement(pElement); + } +#endif + + if (score > bestScore) + { + pBestElement = pElement; + bestScore = score; +#if 0 // set true to output searching informaton + printf("\n-HIDFindSubElement(%ld:%ld)-I-Debug, better score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score); + HIDPrintElement(pBestElement); +#endif + } + pElement = HIDGetNextDeviceElement(pElement, hidMask); + } +#if 0 // set true to output searching informaton + if (pBestElement) + { + printf("\n-HIDFindSubElement(%ld:%ld)-I-Debug, best score: %ld.",pSearchElement->usagePage, pSearchElement->usage, bestScore); + HIDPrintElement(pBestElement); + printf("\n"); + } +#endif + + *ppFoundElement = pBestElement; + return (NULL != pBestElement); +} + +// print out all of an elements information +int HIDPrintElement(const pRecElement pElement) +{ + int results; + int count; + + printf("\n"); + + if (gDepth != pElement->depth) + printf("%d",gDepth); + for (count = 0;count < pElement->depth;count++) + printf(" | "); + +#if 0 // this is verbose + results = + printf("-HIDPrintElement = {name: \"%s\", t: 0x%.2lX, u:%ld:%ld, c: %ld, min/max: %ld/%ld, scaled: %ld/%ld, size: %ld, rel: %s, wrap: %s, nonLinear: %s, preferred: %s, nullState: %s, units: %ld, exp: %ld, cal: %ld/%ld, user: %ld/%ld, depth: %ld}.", + pElement->name, // name of element (c string) + pElement->type, // the type defined by IOHIDElementType in IOHIDKeys.h + pElement->usagePage, // usage page from IOUSBHIDParser.h which defines general usage + pElement->usage, // usage within above page from IOUSBHIDParser.h which defines specific usage + (long) pElement->cookie, // unique value (within device of specific vendorID and productID) which identifies element, will NOT change + pElement->min, // reported min value possible + pElement->max, // reported max value possible + pElement->scaledMin, // reported scaled min value possible + pElement->scaledMax, // reported scaled max value possible + pElement->size, // size in bits of data return from element + pElement->relative ? "YES" : "NO", // are reports relative to last report (deltas) + pElement->wrapping ? "YES" : "NO", // does element wrap around (one value higher than max is min) + pElement->nonLinear ? "YES" : "NO", // are the values reported non-linear relative to element movement + pElement->preferredState ? "YES" : "NO",// does element have a preferred state (such as a button) + pElement->nullState ? "YES" : "NO", // does element have null state + pElement->units, // units value is reported in (not used very often) + pElement->unitExp, // exponent for units (also not used very often) + pElement->calMin, // min returned value (for calibrate call) + pElement->calMax, // max returned value + pElement->userMin, // user set min to scale to (for scale call) + pElement->userMax, // user set max + pElement->depth + ); +#else // this is brief + results = + printf("-HIDPrintElement = {t: 0x%lX, u:%ld:%ld, c: %ld, name: \"%s\", d: %ld}.", + pElement->type, // the type defined by IOHIDElementType in IOHIDKeys.h + pElement->usagePage, // usage page from IOUSBHIDParser.h which defines general usage + pElement->usage, // usage within above page from IOUSBHIDParser.h which defines specific usage + (long) pElement->cookie, // unique value (within device of specific vendorID and productID) which identifies element, will NOT change + pElement->name, // name of element (c string) + pElement->depth + ); +#endif + fflush(stdout); + return results; +} + +// return true if this is a valid device pointer +Boolean HIDIsValidDevice(const pRecDevice pSearchDevice) +{ + pRecDevice pDevice = gpDeviceList; + + while (pDevice) + { + if (pDevice == pSearchDevice) + return true; + pDevice = pDevice->pNext; + } + return false; +} + +// return true if this is a valid element pointer for this device +Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement) +{ + if (HIDIsValidDevice(pSearchDevice)) + { + pRecElement pRecElementTemp = HIDGetFirstDeviceElement(pSearchDevice,kHIDElementTypeAll); + while (pRecElementTemp) + { + if (pRecElementTemp == pSearchElement) + return true; + pRecElementTemp = HIDGetNextDeviceElement(pRecElementTemp,kHIDElementTypeAll); + } + } + return false; +} diff --git a/HID_Utilities.h b/HID_Utilities.h new file mode 100755 index 0000000..67e37c4 --- /dev/null +++ b/HID_Utilities.h @@ -0,0 +1,256 @@ +/* + File: HID_Utilities.h + + Contains: External interface for HID Utilities + + DRI: George Warner + + Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _HID_Utilities_h_ +#define _HID_Utilities_h_ + +#include + +#include +// 10.0.x +//#include +// 10.1.x +#include + +#include + +// ================================== + +#ifdef __cplusplus +extern "C" { +#endif + +// ================================== + +enum +{ + kDefaultUserMin = 0, // default user min and max used for scaling + kDefaultUserMax = 255, +}; + +typedef enum HIDElementTypeMask +{ + kHIDElementTypeInput = 1 << 1, + kHIDElementTypeOutput = 1 << 2, + kHIDElementTypeFeature = 1 << 3, + kHIDElementTypeCollection = 1 << 4, + kHIDElementTypeIO = kHIDElementTypeInput | kHIDElementTypeOutput | kHIDElementTypeFeature, + kHIDElementTypeAll = kHIDElementTypeIO | kHIDElementTypeCollection +}HIDElementTypeMask; + +struct recElement +{ + IOHIDElementType type; // the type defined by IOHIDElementType in IOHIDKeys.h + long usagePage; // usage page from IOUSBHIDParser.h which defines general usage + long usage; // usage within above page from IOUSBHIDParser.h which defines specific usage + IOHIDElementCookie cookie; // unique value (within device of specific vendorID and productID) which identifies element, will NOT change + long min; // reported min value possible + long max; // reported max value possible + long scaledMin; // reported scaled min value possible + long scaledMax; // reported scaled max value possible + long size; // size in bits of data return from element + Boolean relative; // are reports relative to last report (deltas) + Boolean wrapping; // does element wrap around (one value higher than max is min) + Boolean nonLinear; // are the values reported non-linear relative to element movement + Boolean preferredState; // does element have a preferred state (such as a button) + Boolean nullState; // does element have null state + long units; // units value is reported in (not used very often) + long unitExp; // exponent for units (also not used very often) + Str255 name; // name of element (not used often) + +// runtime variables + long minReport; // min returned value + long maxReport; // max returned value (calibrate call) + long userMin; // user set value to scale to (scale call) + long userMax; + + struct recElement * pPrevious; // previous element (NULL at list head) + struct recElement * pChild; // next child (only of collections) + struct recElement * pSibling; // next sibling (for elements and collections) + +}; +typedef struct recElement recElement; +typedef recElement* pRecElement; + +struct recDevice +{ + IOHIDDeviceInterface ** interface; // interface to device, NULL = no interface + IOHIDQueueInterface ** queue; // device queue, NULL = no queue + CFRunLoopSourceRef queueRunLoopSource; // device queue run loop source, NULL == no source + IOHIDOutputTransactionInterface ** transaction; // output transaction interface, NULL == no transaction + io_object_t notification; // notifications + Str255 transport; // device transport + long vendorID; // id for device vendor, unique across all devices + long productID; // id for particular product, unique across all of a vendors devices + long version; // version of product + Str255 manufacturer; // name of manufacturer + Str255 product; // name of product + Str255 serial; // serial number of specific product, can be assumed unique across specific product or specific vendor (not used often) + long locID; // long representing location in USB (or other I/O) chain which device is pluged into, can identify specific device on machine + long usage; // usage page from IOUSBHID Parser.h which defines general usage + long usagePage; // usage within above page from IOUSBHID Parser.h which defines specific usage + long totalElements; // number of total elements (should be total of all elements on device including collections) (calculated, not reported by device) + long features; // number of elements of type kIOHIDElementTypeFeature + long inputs; // number of elements of type kIOHIDElementTypeInput_Misc or kIOHIDElementTypeInput_Button or kIOHIDElementTypeInput_Axis or kIOHIDElementTypeInput_ScanCodes + long outputs; // number of elements of type kIOHIDElementTypeOutput + long collections; // number of elements of type kIOHIDElementTypeCollection + long axis; // number of axis (calculated, not reported by device) + long buttons; // number of buttons (calculated, not reported by device) + long hats; // number of hat switches (calculated, not reported by device) + long sliders; // number of sliders (calculated, not reported by device) + long dials; // number of dials (calculated, not reported by device) + long wheels; // number of wheels (calculated, not reported by device) + recElement* pListElements; // head of linked list of elements + struct recDevice* pNext; // next device +}; +typedef struct recDevice recDevice; +typedef recDevice* pRecDevice; + +// ================================== +// Create and open an interface to device, required prior to extracting values or building queues +// Note: appliction now owns the device and must close and release it prior to exiting +extern IOReturn HIDCreateOpenDeviceInterface (io_object_t hidDevice, pRecDevice pDevice); + +// builds list of device with elements (allocates memory and captures devices) +// list is allcoated internally within HID Utilites and can be accessed via accessor functions +// structures within list are considered flat and user accessable, butnot user modifiable +// can be called again to rebuild list to account for new devices (will do the right thing in case of disposing existing list) +extern Boolean HIDBuildDeviceList (UInt32 usagePage, UInt32 usage); + +// release list built by above function +// MUST be called prior to application exit to properly release devices +// if not called (or app crashes) devices can be recovered by pluging into different location in USB chain +extern void HIDReleaseDeviceList (void); + +// does a device list exist +extern Boolean HIDHaveDeviceList (void); + +// how many HID devices have been found +// returns 0 if no device list exist +extern UInt32 HIDCountDevices (void); + +// how many elements does a specific device have +// returns 0 if device is invalid or NULL +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get non-collection elements +extern UInt32 HIDCountDeviceElements (pRecDevice pDevice, HIDElementTypeMask typeMask); + +// get the first device in the device list +// returns NULL if no list exists +extern pRecDevice HIDGetFirstDevice (void); + +// get next device in list given current device as parameter +// returns NULL if end of list +extern pRecDevice HIDGetNextDevice (pRecDevice pDevice); + +// get the first element of device passed in as parameter +// returns NULL if no list exists or device does not exists or is NULL +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get previous HIDGetFirstDeviceElement functionality +extern pRecElement HIDGetFirstDeviceElement (pRecDevice pDevice, HIDElementTypeMask typeMask); + +// get next element of given device in list given current element as parameter +// will walk down each collection then to next element or collection (depthwise traverse) +// returns NULL if end of list +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get previous HIDGetNextDeviceElement functionality +extern pRecElement HIDGetNextDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask); + +// get previous element of given device in list given current element as parameter +// this wlaks directly up the tree to the top element and does not search at each level +// returns NULL if beginning of list +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get non-collection elements +extern pRecElement HIDGetPreviousDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask); + +// returns C string type name given a type enumeration passed in as parameter (see IOHIDKeys.h) +// returns empty string for invlid types +extern void HIDGetTypeName (IOHIDElementType type, char * cstrName); + +// returns C string usage given usage page and usage passed in as parameters (see IOUSBHIDParser.h) +// returns usage page and usage values in string form for unknown values +extern void HIDGetUsageName (long valueUsagePage, long valueUsage, char * cstrName); + +// returns calibrated value given raw value passed in +// calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values +extern SInt32 HIDCalibrateValue (SInt32 value, pRecElement pElement); + +// returns scaled value given raw value passed in +// scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values +extern SInt32 HIDScaleValue (SInt32 value, pRecElement pElement); + +// --------------------------------- +// convert an element type to a mask +extern HIDElementTypeMask HIDConvertElementTypeToMask (const long type); + +// find this device +extern Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice); + +// find the device and element for this action +// Device: serial, vendorID, productID, location, usagePage, usage +// Element: cookie, usagePage, usage, +extern Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement, + pRecDevice *ppFoundDevice, pRecElement *ppFoundElement); + +// find the device and element for this action +// Device: serial, vendorID, productID, location, usagePage, usage +// Element: cookie, usagePage, usage, + +extern Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement); + +// print out all of an elements information +extern int HIDPrintElement(const pRecElement pElement); + +// return true if this is a valid device pointer +extern Boolean HIDIsValidDevice(const pRecDevice pSearchDevice); + +// return true if this is a valid element pointer for this device +extern Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement); + +#ifdef __cplusplus +} +#endif + +#endif // _HID_Utilities_h_ diff --git a/HID_Utilities_External.h b/HID_Utilities_External.h new file mode 100755 index 0000000..dd79138 --- /dev/null +++ b/HID_Utilities_External.h @@ -0,0 +1,476 @@ +/* + File: HID_Utilities_External.h + + Contains: Definition of the HID Utilities exported functions + + DRI: George Warner + + Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _HID_Utilities_External_h_ +#define _HID_Utilities_External_h_ + +// ================================== +//includes + +#if TARGET_RT_MAC_CFM + typedef void (*IOHIDCallbackFunction)(void * target, unsigned long result, void* refcon, void * sender); +#else + #include +#endif TARGET_RT_MAC_CFM + +#include + +#if 0 +#include + +#include "PID.h" // NOTE: These are now in +#include "IOHIDPowerUsage.h" // NOTE: These are now in +#endif + +#ifdef __MWERKS__ +#define IOHIDEventStruct void +#endif +// ================================== + +#ifdef __cplusplus +extern "C" { +#endif + +// ================================== +// Device and Element Interfaces + +typedef enum HIDElementTypeMask +{ + kHIDElementTypeInput = 1 << 1, + kHIDElementTypeOutput = 1 << 2, + kHIDElementTypeFeature = 1 << 3, + kHIDElementTypeCollection = 1 << 4, + kHIDElementTypeIO = kHIDElementTypeInput | kHIDElementTypeOutput | kHIDElementTypeFeature, + kHIDElementTypeAll = kHIDElementTypeIO | kHIDElementTypeCollection +}HIDElementTypeMask; + +struct recElement +{ + unsigned long type; // the type defined by IOHIDElementType in IOHIDKeys.h + long usagePage; // usage page from IOUSBHIDParser.h which defines general usage + long usage; // usage within above page from IOUSBHIDParser.h which defines specific usage + void * cookie; // unique value (within device of specific vendorID and productID) which identifies element, will NOT change + long min; // reported min value possible + long max; // reported max value possible + long scaledMin; // reported scaled min value possible + long scaledMax; // reported scaled max value possible + long size; // size in bits of data return from element + unsigned char relative; // are reports relative to last report (deltas) + unsigned char wrapping; // does element wrap around (one value higher than max is min) + unsigned char nonLinear; // are the values reported non-linear relative to element movement + unsigned char preferredState; // does element have a preferred state (such as a button) + unsigned char nullState; // does element have null state + long units; // units value is reported in (not used very often) + long unitExp; // exponent for units (also not used very often) + char name[256]; // name of element (c string) + +// runtime variables + long calMin; // min returned value + long calMax; // max returned value (calibrate call) + long userMin; // user set value to scale to (scale call) + long userMax; + + struct recElement * pPrevious; // previous element (NULL at list head) + struct recElement * pChild; // next child (only of collections) + struct recElement * pSibling; // next sibling (for elements and collections) + + long depth; +}; +typedef struct recElement recElement; +typedef recElement* pRecElement; + +struct recDevice +{ + void * interface; // interface to device, NULL = no interface + void * queue; // device queue, NULL = no queue + void * queueRunLoopSource; // device queue run loop source, NULL == no source + void * transaction; // output transaction interface, NULL == no interface + void * notification; // notifications + char transport[256]; // device transport (c string) + long vendorID; // id for device vendor, unique across all devices + long productID; // id for particular product, unique across all of a vendors devices + long version; // version of product + char manufacturer[256]; // name of manufacturer + char product[256]; // name of product + char serial[256]; // serial number of specific product, can be assumed unique across specific product or specific vendor (not used often) + long locID; // long representing location in USB (or other I/O) chain which device is pluged into, can identify specific device on machine + long usage; // usage page from IOUSBHID Parser.h which defines general usage + long usagePage; // usage within above page from IOUSBHID Parser.h which defines specific usage + long totalElements; // number of total elements (should be total of all elements on device including collections) (calculated, not reported by device) + long features; // number of elements of type kIOHIDElementTypeFeature + long inputs; // number of elements of type kIOHIDElementTypeInput_Misc or kIOHIDElementTypeInput_Button or kIOHIDElementTypeInput_Axis or kIOHIDElementTypeInput_ScanCodes + long outputs; // number of elements of type kIOHIDElementTypeOutput + long collections; // number of elements of type kIOHIDElementTypeCollection + long axis; // number of axis (calculated, not reported by device) + long buttons; // number of buttons (calculated, not reported by device) + long hats; // number of hat switches (calculated, not reported by device) + long sliders; // number of sliders (calculated, not reported by device) + long dials; // number of dials (calculated, not reported by device) + long wheels; // number of wheels (calculated, not reported by device) + recElement* pListElements; // head of linked list of elements + struct recDevice* pNext; // next device +}; +typedef struct recDevice recDevice; +typedef recDevice* pRecDevice; + +// ================================== +// HID Utilities interface +// ================================== +// Create and open an interface to device, required prior to extracting values or building queues +// Note: appliction now owns the device and must close and release it prior to exiting +extern unsigned long HIDCreateOpenDeviceInterface (UInt32 hidDevice, pRecDevice pDevice); + +// builds list of device with elements (allocates memory and captures devices) +// list is allcoated internally within HID Utilites and can be accessed via accessor functions +// structures within list are considered flat and user accessable, butnot user modifiable +// can be called again to rebuild list to account for new devices (will do the right thing in case of disposing existing list) +extern Boolean HIDBuildDeviceList (UInt32 usagePage, UInt32 usage); + +// release list built by above function +// MUST be called prior to application exit to properly release devices +// if not called (or app crashes) devices can be recovered by pluging into different location in USB chain +extern void HIDReleaseDeviceList (void); + +// does a device list exist +extern Boolean HIDHaveDeviceList (void); + +// how many HID devices have been found +// returns 0 if no device list exist +extern UInt32 HIDCountDevices (void); + +// how many elements does a specific device have +// returns 0 if device is invalid or NULL +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get non-collection elements +extern UInt32 HIDCountDeviceElements (pRecDevice pDevice, HIDElementTypeMask typeMask); + +// get the first device in the device list +// returns NULL if no list exists +extern pRecDevice HIDGetFirstDevice (void); + +// get next device in list given current device as parameter +// returns NULL if end of list +extern pRecDevice HIDGetNextDevice (pRecDevice pDevice); + +// get the first element of device passed in as parameter +// returns NULL if no list exists or device does not exists or is NULL +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get previous HIDGetFirstDeviceElement functionality +extern pRecElement HIDGetFirstDeviceElement (pRecDevice pDevice, HIDElementTypeMask typeMask); + +// get next element of given device in list given current element as parameter +// will walk down each collection then to next element or collection (depthwise traverse) +// returns NULL if end of list +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get previous HIDGetNextDeviceElement functionality +extern pRecElement HIDGetNextDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask); + +// get previous element of given device in list given current element as parameter +// this wlaks directly up the tree to the top element and does not search at each level +// returns NULL if beginning of list +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get non-collection elements +extern pRecElement HIDGetPreviousDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask); + +// returns C string type name given a type enumeration passed in as parameter (see IOHIDKeys.h) +// returns empty string for invlid types +extern void HIDGetTypeName (IOHIDElementType theType, char * cstrName); + +// set name from vendor id/product id look up (using cookies) +extern Boolean HIDGetElementNameFromVendorProductCookie (const long vendorID, const long productID, const long cookie, char * pName); + +// set name from vendor id/product id look up (using usage page & usage) +extern Boolean HIDGetElementNameFromVendorProductUsage (const long vendorID, const long productID, const long pUsagePage, const long pUsage, char * pName); + +// returns C string usage given usage page and usage passed in as parameters (see IOUSBHIDParser.h) +// returns usage page and usage values in string form for unknown values +extern void HIDGetUsageName (long valueUsagePage, long valueUsage, char * cstrName); + +// returns calibrated value given raw value passed in +// calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values +// extern SInt32 HIDCalibrateValue (SInt32 value, pRecElement pElement); + +// returns scaled value given raw value passed in +// scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values +// extern SInt32 HIDScaleValue (SInt32 value, pRecElement pElement); + +// --------------------------------- +// convert an element type to a mask +extern HIDElementTypeMask HIDConvertElementTypeToMask (const long type); + +// find this device +extern Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice); + +// find the device and element for this action +// Device: serial, vendorID, productID, location, usagePage, usage +// Element: cookie, usagePage, usage, +extern Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement, + pRecDevice *ppFoundDevice, pRecElement *ppFoundElement); + +// find the device and element for this action +// Device: serial, vendorID, productID, location, usagePage, usage +// Element: cookie, usagePage, usage, + +extern Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement); + +// print out all of an elements information +extern int HIDPrintElement(const pRecElement pElement); + +// return true if this is a valid device pointer +extern Boolean HIDIsValidDevice(const pRecDevice pSearchDevice); + +// return true if this is a valid element pointer for this device +extern Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement); + +// ================================== +// Element Event Queue and Value Interfaces + +enum +{ + kDefaultUserMin = 0, // default user min and max used for scaling + kDefaultUserMax = 255 +}; + +enum +{ + kDeviceQueueSize = 50 // this is wired kernel memory so should be set to as small as possible + // but should account for the maximum possible events in the queue + // USB updates will likely occur at 100 Hz so one must account for this rate of + // if states change quickly (updates are only posted on state changes) +}; + +// ================================== +// queues specific element, performing any device queue set up required +extern unsigned long HIDQueueElement (pRecDevice pDevice, pRecElement pElement); + +// adds all elements to queue, performing any device queue set up required +extern unsigned long HIDQueueDevice (pRecDevice pDevice); + +// removes element for queue, if last element in queue will release queue and device +extern unsigned long HIDDequeueElement (pRecDevice pDevice, pRecElement pElement); + +// completely removes all elements from queue and releases queue and device +extern unsigned long HIDDequeueDevice (pRecDevice pDevice); + +// releases all device queues for quit or rebuild (must be called) +extern unsigned long HIDReleaseAllDeviceQueues (void); + +// releases interface to device, should be done prior to exiting application (called from HIDReleaseDeviceList) +extern unsigned long HIDCloseReleaseInterface (pRecDevice pDevice); + +// returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise +// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned char HIDGetEvent (pRecDevice pDevice, void * pHIDEvent); + +// returns current value for element, creating device interface as required, polling element +extern long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement); + +// Set an elements value +// NOTE: This should only be used when a single element report needs to be sent. +// If multiple elements reports are to be send then transactions should be used. +// pIOHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern long HIDSetElementValue (pRecDevice pDevice, pRecElement pElement,void* pIOHIDEvent); + +// Set a callback to be called when a queue goes from empty to non-empty +extern long HIDSetQueueCallback (pRecDevice pDevice, IOHIDCallbackFunction callback); + +#if 0 +// Get a report from a device +extern long HIDGetReport (pRecDevice pDevice,const IOHIDReportType reportType, const unsigned long reportID, void* reportBuffer, unsigned long* reportBufferSize); + +// Send a report to a device +extern long HIDSetReport (pRecDevice pDevice,const IOHIDReportType reportType, const unsigned long reportID, void* reportBuffer, const unsigned long reportBufferSize); +#endif + +// ================================== +// HUD utilities interfaces + +// returns calibrated value given raw value passed in +// calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values +extern long HIDCalibrateValue (long value, pRecElement pElement); + +// returns scaled value given raw value passed in +// scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values +extern long HIDScaleValue (long value, pRecElement pElement); + +// convert an element type to a mask +extern HIDElementTypeMask HIDConvertElementTypeToMask (const long type); + +// find this device +extern Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice); + +// find the device and element for this action +// Device: serial, vendorID, productID, location, usagePage, usage +// Element: cookie, usagePage, usage, +extern Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement, + pRecDevice *ppFoundDevice, pRecElement *ppFoundElement); +// find the device and element for this action +// Device: serial, vendorID, productID, location, usagePage, usage +// Element: cookie, usagePage, usage, + +extern Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement); + +// print out all of an elements information +extern int HIDPrintElement(const pRecElement pElement); + +// return true if this is a valid device pointer +extern Boolean HIDIsValidDevice(const pRecDevice pSearchDevice); + +// return true if this is a valid element pointer for this device +extern Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement); + +// ================================== +// Name Lookup Interfaces + +// set name from vendor id/product id look up (using cookies) +extern Boolean HIDGetElementNameFromVendorProductCookie (const long vendorID, const long productID, const long cookie, char * pName); + +// set name from vendor id/product id look up (using usage page & usage) +extern Boolean HIDGetElementNameFromVendorProductUsage (const long vendorID, const long productID, const long pUsagePage, const long pUsage, char * pName); + +// ================================== +// Conguration and Save Interfaces + +enum +{ + kPercentMove = 10 // precent of overall range a element must move to register +}; + +typedef struct recSaveHID +{ + long actionCookie; + // device + // need to add serial number when I have a test case + long vendorID; + long productID; + long locID; + long usage; + long usagePage; + // elements + long usagePageE; + long usageE; + void * cookie; +}recSaveHID,*pRecSaveHID; + +// polls all devices and elements for a change greater than kPercentMove. Times out after given time +// returns true and pointer to device and element if found +// returns false and NULL for both parameters if not found +extern unsigned char HIDConfigureAction (pRecDevice * ppDevice, pRecElement * ppElement, float timeout); + +// take input records, save required info +// assume file is open and at correct position. +extern void HIDSaveElementConfig (FILE * fileRef, pRecDevice pDevice, pRecElement pElement, long actionCookie); + +// take file, read one record (assume file position is correct and file is open) +// search for matching device +// return pDevice, pElement and cookie for action +extern long HIDRestoreElementConfig (FILE * fileRef, pRecDevice * ppDevice, pRecElement * ppElement); + +// Save the device & element values into the specified key in the specified applications preferences +extern Boolean HIDSaveElementPref (CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice pDevice, pRecElement pElement); + +// Find the specified preference in the specified application +// search for matching device and element +// return pDevice, pElement that matches + +extern Boolean HIDRestoreElementPref (CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice * ppDevice, pRecElement * ppElement); + +// ================================== +// Output Transaction interface + +// Create and open an transaction interface to device, required prior to extracting values or building Transactions +extern unsigned long HIDTransactionAddElement(pRecDevice pDevice, pRecElement pElement); + +// removes an element from a Transaction +extern unsigned long HIDTransactionRemoveElement(pRecDevice pDevice, pRecElement pElement); + +// return true if this transaction contains this element +extern Boolean HIDTransactionHasElement(pRecDevice pDevice, pRecElement pElement); + +/* This changes the default value of an element, when the values of the */ +/* elements are cleared, on clear or commit, they are reset to the */ +/* default value */ +/* This call can be made on elements that are not in the transaction, but */ +/* has undefined behavior if made on elements not in the transaction */ +/* which are later added to the transaction. */ +/* In other words, an element should be added before its default is */ +/* set, for well defined behavior. */ +// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned long HIDTransactionSetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); + +/* Get the current setting of an element's default value */ +// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned long HIDTransactionGetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); + +/* Add a change to the transaction, by setting an element value */ +/* The change is not actually made until it is commited */ +/* The element must be part of the transaction or this call will fail */ +// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned long HIDTransactionSetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); + +/* Get the current setting of an element value */ +// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned long HIDTransactionGetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); + +/* Commit the transaction, or clear all the changes and start over */ +/* timoutMS is the timeout in milliseconds, a zero timeout will cause */ +/* this call to be non-blocking (returning queue empty) if there */ +/* is a NULL callback, and blocking forever until the queue is */ +/* non-empty if their is a valid callback */ +/* callback, if non-NULL is a callback to be called when data is */ +/* inserted to the queue */ +/* callbackTarget and callbackRefcon are passed to the callback */ +extern unsigned long HIDTransactionCommit(pRecDevice pDevice); + +/* Clear all the changes and start over */ +extern unsigned long HIDTransactionClear(pRecDevice pDevice); + +// ================================== + +#ifdef __cplusplus +} +#endif + +#endif // _HID_Utilities_External_h_ diff --git a/HID_Utilities_Internal.h b/HID_Utilities_Internal.h new file mode 100755 index 0000000..3e1eac2 --- /dev/null +++ b/HID_Utilities_Internal.h @@ -0,0 +1,54 @@ +/* + File: HID_Utilities_Internal.h + + Contains: Definition of HID Utilities internal functions + + DRI: George Warner + + Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _HID_Utilities_Internal_h_ +#define _HID_Utilities_Internal_h_ + +// Moved into specific "HID_xxx.h" files. + +#include "HID_Error_Handler.h" + +#endif // _HID_Utilities_Internal_h_ + diff --git a/ImmrHIDUtilAddOn.c b/ImmrHIDUtilAddOn.c new file mode 100755 index 0000000..6d2cbaf --- /dev/null +++ b/ImmrHIDUtilAddOn.c @@ -0,0 +1,95 @@ +/* + * ImmrHIDUtilAddOn.c + * UseFFAPIFromHIDUtilities + * + * Created by rlacroix on Wed Oct 16 2002. + * Copyright (c) 2002 Immersion Corporation. All rights reserved. + * + */ + +#include +#include + +#include +#include +#include +#include + +#include "HID_Utilities_External.h" +#include "ImmrHIDUtilAddOn.h" + +//--------------------------------------------------------------------------------- +// +// AllocateHIDObjectFromRecDevice() +// +// returns: +// NULL, or acceptable io_object_t +// +//--------------------------------------------------------------------------------- +io_service_t AllocateHIDObjectFromRecDevice( pRecDevice pDevice ) +{ + CFMutableDictionaryRef matchingDict; + UInt32 locationID = pDevice->locID; + CFNumberRef refUsage = NULL; + mach_port_t masterPort = NULL; + IOReturn result = kIOReturnSuccess; + io_service_t hidDevice = NULL; + + do // while( 0 ) + { + result = IOMasterPort (bootstrap_port, &masterPort); + if( result != kIOReturnSuccess ) + { + break; + } + + // Set up the matching criteria for the devices we're interested in. + // We are interested in instances of class IOHIDDevice. + // matchingDict is consumed below (in IOServiceGetMatchingService) + // so we have no leak here. + // + matchingDict = IOServiceMatching(kIOHIDDeviceKey); + if (!matchingDict) + { + break; + } + + // Add a key for locationID to our matching dictionary. This works for matching to + // IOHIDDevices, so we will only look for a device attached to that particular port + // on the machine. + // + refUsage = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &locationID); + CFDictionaryAddValue( matchingDict, + CFSTR(kIOHIDLocationIDKey), + refUsage); + CFRelease(refUsage); + + // IOServiceGetMatchingService assumes that we already know that there is only one device + // that matches. This way we don't have to do the whole iteration dance to look at each + // device that matches. This is a new API in 10.2 + // + hidDevice = IOServiceGetMatchingService( masterPort, matchingDict); + } + while( 0 ); + + // Free master port if we created one. + // + if (masterPort) + mach_port_deallocate(mach_task_self(), masterPort); + + return hidDevice; +} + +//--------------------------------------------------------------------------------- +// +// FreeHIDObject() +// +//--------------------------------------------------------------------------------- +bool FreeHIDObject( io_service_t hidDevice ) +{ + kern_return_t kr; + + kr = IOObjectRelease(hidDevice); + + return( kIOReturnSuccess == kr ); +} \ No newline at end of file diff --git a/ImmrHIDUtilAddOn.h b/ImmrHIDUtilAddOn.h new file mode 100755 index 0000000..76ef5e9 --- /dev/null +++ b/ImmrHIDUtilAddOn.h @@ -0,0 +1,11 @@ +/* + * ImmrHIDUtilAddOn.h + * UseFFAPIFromHIDUtilities + * + * Created by rlacroix on Wed Oct 16 2002. + * Copyright (c) 2002 Immersion Corporation. All rights reserved. + * + */ + +extern io_object_t AllocateHIDObjectFromRecDevice( pRecDevice pDevice ); +extern bool FreeHIDObject( io_object_t hidDevice ); \ No newline at end of file diff --git a/game.xcodeproj/project.pbxproj b/game.xcodeproj/project.pbxproj index 8f33d1b..8e3d244 100644 --- a/game.xcodeproj/project.pbxproj +++ b/game.xcodeproj/project.pbxproj @@ -11,6 +11,14 @@ 7489D5F11CAFF9D10063AC48 /* ASWAppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7489D5ED1CAFF9D00063AC48 /* ASWAppKit.framework */; }; 7489D5F21CAFF9D10063AC48 /* ASWDebug.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7489D5EE1CAFF9D10063AC48 /* ASWDebug.framework */; }; 7489D5F31CAFF9D10063AC48 /* ASWFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7489D5EF1CAFF9D10063AC48 /* ASWFoundation.framework */; }; + 7489D6071CB0002C0063AC48 /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7489D6061CB0002C0063AC48 /* ForceFeedback.framework */; settings = {ASSET_TAGS = (); }; }; + 7489D60E1CB000520063AC48 /* HID_Config_Utilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 7489D6081CB000520063AC48 /* HID_Config_Utilities.c */; settings = {ASSET_TAGS = (); }; }; + 7489D60F1CB000520063AC48 /* HID_Error_Handler.c in Sources */ = {isa = PBXBuildFile; fileRef = 7489D6091CB000520063AC48 /* HID_Error_Handler.c */; settings = {ASSET_TAGS = (); }; }; + 7489D6101CB000520063AC48 /* HID_Name_Lookup.c in Sources */ = {isa = PBXBuildFile; fileRef = 7489D60A1CB000520063AC48 /* HID_Name_Lookup.c */; settings = {ASSET_TAGS = (); }; }; + 7489D6111CB000520063AC48 /* HID_Queue_Utilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 7489D60B1CB000520063AC48 /* HID_Queue_Utilities.c */; settings = {ASSET_TAGS = (); }; }; + 7489D6121CB000520063AC48 /* HID_Transaction_Utilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 7489D60C1CB000520063AC48 /* HID_Transaction_Utilities.c */; settings = {ASSET_TAGS = (); }; }; + 7489D6131CB000520063AC48 /* HID_Utilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 7489D60D1CB000520063AC48 /* HID_Utilities.c */; settings = {ASSET_TAGS = (); }; }; + 7489D61C1CB000F00063AC48 /* ImmrHIDUtilAddOn.c in Sources */ = {isa = PBXBuildFile; fileRef = 7489D61A1CB000F00063AC48 /* ImmrHIDUtilAddOn.c */; settings = {ASSET_TAGS = (); }; }; 7F06105A0876ED46001EA95C /* ai.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F060FE50876ED46001EA95C /* ai.cpp */; }; 7F06105D0876ED46001EA95C /* carphysics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F060FEA0876ED46001EA95C /* carphysics.cpp */; }; 7F06105E0876ED46001EA95C /* carselection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F060FEC0876ED46001EA95C /* carselection.cpp */; }; @@ -106,6 +114,21 @@ 7489D5ED1CAFF9D00063AC48 /* ASWAppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ASWAppKit.framework; path = Frameworks/ASWAppKit.framework; sourceTree = ""; }; 7489D5EE1CAFF9D10063AC48 /* ASWDebug.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ASWDebug.framework; path = Frameworks/ASWDebug.framework; sourceTree = ""; }; 7489D5EF1CAFF9D10063AC48 /* ASWFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ASWFoundation.framework; path = Frameworks/ASWFoundation.framework; sourceTree = ""; }; + 7489D6061CB0002C0063AC48 /* ForceFeedback.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ForceFeedback.framework; path = Frameworks/ForceFeedback.framework; sourceTree = ""; }; + 7489D6081CB000520063AC48 /* HID_Config_Utilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = HID_Config_Utilities.c; sourceTree = ""; }; + 7489D6091CB000520063AC48 /* HID_Error_Handler.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = HID_Error_Handler.c; sourceTree = ""; }; + 7489D60A1CB000520063AC48 /* HID_Name_Lookup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = HID_Name_Lookup.c; sourceTree = ""; }; + 7489D60B1CB000520063AC48 /* HID_Queue_Utilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = HID_Queue_Utilities.c; sourceTree = ""; }; + 7489D60C1CB000520063AC48 /* HID_Transaction_Utilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = HID_Transaction_Utilities.c; sourceTree = ""; }; + 7489D60D1CB000520063AC48 /* HID_Utilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = HID_Utilities.c; sourceTree = ""; }; + 7489D6141CB000620063AC48 /* HID_Utilities_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HID_Utilities_Internal.h; sourceTree = ""; }; + 7489D6151CB0006F0063AC48 /* HID_Error_Handler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HID_Error_Handler.h; sourceTree = ""; }; + 7489D6161CB0006F0063AC48 /* HID_Name_Lookup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HID_Name_Lookup.h; sourceTree = ""; }; + 7489D6171CB0006F0063AC48 /* HID_Queue_Utilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HID_Queue_Utilities.h; sourceTree = ""; }; + 7489D6181CB0007A0063AC48 /* HID_Utilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HID_Utilities.h; sourceTree = ""; }; + 7489D6191CB000850063AC48 /* HID_Utilities_External.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HID_Utilities_External.h; sourceTree = ""; }; + 7489D61A1CB000F00063AC48 /* ImmrHIDUtilAddOn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ImmrHIDUtilAddOn.c; sourceTree = ""; }; + 7489D61B1CB000F00063AC48 /* ImmrHIDUtilAddOn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImmrHIDUtilAddOn.h; sourceTree = ""; }; 7F060FE50876ED46001EA95C /* ai.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ai.cpp; sourceTree = ""; }; 7F060FEA0876ED46001EA95C /* carphysics.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = carphysics.cpp; sourceTree = ""; }; 7F060FEB0876ED46001EA95C /* carphysics.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = carphysics.h; sourceTree = ""; }; @@ -274,6 +297,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 7489D6071CB0002C0063AC48 /* ForceFeedback.framework in Frameworks */, 8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */, 7FC1DAFD087820860029047D /* AGL.framework in Frameworks */, 7FC1DB0E087820970029047D /* QuickTime.framework in Frameworks */, @@ -338,6 +362,7 @@ 20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */ = { isa = PBXGroup; children = ( + 7489D6061CB0002C0063AC48 /* ForceFeedback.framework */, 7489D5EC1CAFF9D00063AC48 /* AmbrosiaTools.framework */, 7489D5ED1CAFF9D00063AC48 /* ASWAppKit.framework */, 7489D5EE1CAFF9D10063AC48 /* ASWDebug.framework */, @@ -471,6 +496,20 @@ 7F06136E087703B4001EA95C /* HID */ = { isa = PBXGroup; children = ( + 7489D6081CB000520063AC48 /* HID_Config_Utilities.c */, + 7489D6091CB000520063AC48 /* HID_Error_Handler.c */, + 7489D60A1CB000520063AC48 /* HID_Name_Lookup.c */, + 7489D60B1CB000520063AC48 /* HID_Queue_Utilities.c */, + 7489D60C1CB000520063AC48 /* HID_Transaction_Utilities.c */, + 7489D60D1CB000520063AC48 /* HID_Utilities.c */, + 7489D6141CB000620063AC48 /* HID_Utilities_Internal.h */, + 7489D6151CB0006F0063AC48 /* HID_Error_Handler.h */, + 7489D6161CB0006F0063AC48 /* HID_Name_Lookup.h */, + 7489D6171CB0006F0063AC48 /* HID_Queue_Utilities.h */, + 7489D6181CB0007A0063AC48 /* HID_Utilities.h */, + 7489D6191CB000850063AC48 /* HID_Utilities_External.h */, + 7489D61A1CB000F00063AC48 /* ImmrHIDUtilAddOn.c */, + 7489D61B1CB000F00063AC48 /* ImmrHIDUtilAddOn.h */, 7FD85DEA08BC79EF00C3EB17 /* HID_Config_Utilities.c */, 7FD85DEB08BC79EF00C3EB17 /* HID_Error_Handler.c */, 7FD85DEC08BC79EF00C3EB17 /* HID_Name_Lookup.c */, @@ -606,18 +645,24 @@ 7F0610670876ED46001EA95C /* entities.cpp in Sources */, 7F0610680876ED46001EA95C /* environment.cpp in Sources */, 7F0610690876ED46001EA95C /* fileio.cpp in Sources */, + 7489D61C1CB000F00063AC48 /* ImmrHIDUtilAddOn.c in Sources */, 7F06106A0876ED46001EA95C /* gameframe.cpp in Sources */, 7F06106B0876ED46001EA95C /* gameinitexit.cpp in Sources */, 7F06106D0876ED46001EA95C /* infodisplay.cpp in Sources */, + 7489D60E1CB000520063AC48 /* HID_Config_Utilities.c in Sources */, 7F06106E0876ED46001EA95C /* initexit.cpp in Sources */, 7F0610700876ED46001EA95C /* interfacemultiplayer.cpp in Sources */, 7F0610710876ED46001EA95C /* interfaceoptions.cpp in Sources */, 7F0610720876ED46001EA95C /* interfaceutil.cpp in Sources */, 7F0610730876ED46001EA95C /* lights.cpp in Sources */, + 7489D6101CB000520063AC48 /* HID_Name_Lookup.c in Sources */, 7F0610740876ED46001EA95C /* log.cpp in Sources */, 7F0610750876ED46001EA95C /* maccontrols.cpp in Sources */, + 7489D6121CB000520063AC48 /* HID_Transaction_Utilities.c in Sources */, + 7489D60F1CB000520063AC48 /* HID_Error_Handler.c in Sources */, 7F0610760876ED46001EA95C /* macerror.cpp in Sources */, 7F0610770876ED46001EA95C /* macfileio.cpp in Sources */, + 7489D6131CB000520063AC48 /* HID_Utilities.c in Sources */, 7F0610780876ED46001EA95C /* maclocaltracker.cpp in Sources */, 7F0610790876ED46001EA95C /* macscreen.cpp in Sources */, 7F06107A0876ED46001EA95C /* macsystem.cpp in Sources */, @@ -642,6 +687,7 @@ 7F0610910876ED46001EA95C /* textures.cpp in Sources */, 7F0610920876ED46001EA95C /* tire.cpp in Sources */, 7F0610930876ED46001EA95C /* tracker.cpp in Sources */, + 7489D6111CB000520063AC48 /* HID_Queue_Utilities.c in Sources */, 7F0610940876ED46001EA95C /* tracks.cpp in Sources */, 7F0610950876ED46001EA95C /* transparency.cpp in Sources */, 7F0610960876ED46001EA95C /* vectors.cpp in Sources */,